`
hyj1254
  • 浏览: 336108 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

JS 超类和子类

阅读更多
先引一段原文,可略过..
  .....Object is the superclass of all the built-in classes, and all classes inherit a few basic methods from Object.
  Recall that objects inherit properties from the prototype object of their constructor. How do they also inherit properties from the Object class? Remember that the prototype object is itself an object; it is created with the Object( ) constructor. This means the prototype object itself inherits properties from Object.prototype! Prototype-based inheritance is not limited to a single prototype object; instead, a chain of prototype objects is involved. Thus, a Complex object inherits properties from Complex.prototype and from Object.prototype. When you look up a property in a Complex object, the object itself is searched first. If the property is not found, the Complex.prototype object is searched next. Finally, if the property is not found in that object, the Object.prototype object is searched.

    这段话前半部分描述了一个重要信息:prototype由构造函数Object()创建,所以它本身也是一个Object实例,而任何Object实例都可以从Object.prototype中继承属性;于是prototype就也具有了这种能力。
  这就引出了另一个重要的信息:基于prototype的继承不仅仅局限于单一的prototype对象,访问沿着一条prototype链逐级向上执行:假设有个Complex实例,访问其中一属性,如果本身找不到,便访问Complex.prototype对象;还找不到即在Object实例中找不到,就接着访问Complex.prototype的上一级--Object.prototype。
  这就解释了为什么JS对象都从Object对象中继承了方法:如自定义了Complex类,然后它的每个实例就都能访问toString()方法,因为它的prototype是Object实例,能访问Object.prototype。
  这就是所谓“超类和子类”的核心。拿上例来说,它所表述的是,由于Complex.prototype默认是Object的实例(由Object()初始化),于是Complex便继承了Object(即可以访问Object和Object.prototype的所有属性)
    好戏登场了:只要把Complex.prototype的构造函数换成其他的,而不是默认的Object(),那Complex便成为了那个类的子类;这就实现了自己定义的超类和子类关系。当然Complex还是Object的子类,但那是因为那个类最终也是Object的子类。
    举例说明(以Person和Man为例):
function Person(name){this.name=name;}
Person.prototype.say=function(){alert("hello");}
function Man(){}
Man.prototype=new Person("Tom");
//------------
var man = new Man();
alert(man.name);//Tom,继承了Person实例的属性:name
man.say();//hello,继承了Person.prototype的属性:say
alert(man.hasOwnProperty('name'));//false,name在Man.prototype中

完工了,Man已经成为了Person的子类。
当然,这样写虽然能达到效果,但可能不符合“标准”,那就换成标准的:
function Person(name){this.name=name;}
Person.prototype.say=function(){alert(this.hasOwnProperty('name'));}
function Man(name){
   Person.call(this,name);//多了这一步,实现实例属性的继承,要先明白call的作用
}
Man.prototype=new Person();//继承Person.prototype的属性。
//--------------
var man = new Man("Tom");
alert(man.constructor==Person);//true
Man.prototype.constructor=Man;//将Man的构造函数指回Man
alert(man.name);//Tom
alert(man.hasOwnProperty('name'));//true,通过call方法,name已经成为man的实例属性。hasOwnProperty判断man本身是否具有name属性。
man.say();//true,继承了Person.prototype的属性,this指向man
alert(Man.prototype.constructor==Person);//false
alert(Man.prototype instanceof Person);//true


这就是“标准”的做法。当然也可以突发奇想,让Man只继承Person.prototype的属性,而不包括Person的实例属性。
function Person(name){this.name=name;}
Person.prototype.say=function(){alert('hello');}
function Man(){}
Man.prototype=Person.prototype;
var man = new Man();
alert(man.name);//undefined,没有继承Person实例的属性
man.say();//hello,继承了Person.prototype的属性:say
alert(Man.prototype.constructor==Object);//true
alert(Man.prototype instanceof Object);//true

总之,Man是谁的子类就看Man.prototype是由谁的构造函数初始化的。只要把握了这点,继承关系可以随心所欲的构造。
但注意,试图通过把子类的prototype的constructor设为父类的构造函数是不行的。因为prototype并没有被父类的构造函数初始化,它还是由Object()初始化,只是它的constructor属性值改为父类了。 当子类实例访问"父类"prototype内的同名方法时,并不会到"父类"里查找,而是查找Object及Object.prototype。
Man.prototype.constructor=Person;//这样达不到继承的目的

另外说说call的作用(apply也一样):
function Man(name){Person.call(this,name);}

调用Person的构造函数Person,call的第一个参数是绑定Person函数的临时对象,后面的参数是要传给Person的。此例中this即Man实例绑定了Person函数,并调用它。然后person方法内的this指向的就不再是Person实例了,而是Man实例,最终效果就好像它是Man的构造函数一样:所有Man实例就都有了Person实例的属性。
1
0
分享到:
评论
1 楼 Hedgehogking 2013-02-20  
额~菜鸟我看的有点晕晕的了

相关推荐

    javascript闭包子类超类理解

    javascript闭包子类超类简介,有利于初学者对该技术的理解。

    JavaScript 面向对象编程详细讲解文档

    我们将会解释如何模拟继承及其超类与子类之间关系的形式。原型是理解继承概念的关键, 我们将会教你如何建立原型, 如何检测一个对象是否是另外一个对象的原型, 及其 JavaScript 的模型与Java 面向对象编程之间的区别...

    javascript面向对象三大特征之继承实例详解

    在JavaScript中的继承的实质就是子代可以拥有父代公开的一些属性和方法,在js编程时,我们一般将相同的属性放到父类中,然后在子类定义自己独特的属性,这样的好处是减少代码重复。继承是面向对象的基础,是代码重用...

    Javascript 继承机制的实现

    选定基类后,就可以创建它的子类了。...子类还可添加超类中没有的新属性和方法,也可以覆盖超类中的属性和方法。 4.2.1 继承的方式 和其他功能一样,ECMAScript中实现继承的方式不止一种。这是因为JavaScr

    Starfield:AP计算机科学专业课程美国Simon Lomon高中的Simon的APCSA课程的编程任务

    Particle超类和Oddball子类。 所有粒子必须存储在超类类型的单个数组中。 确保您没有不必要地在Oddball子类中重复继承的变量和函数。 您的Oddball子类只需要包含一个构造函数以及void move()和/或void show()以便...

    super-prop:为超类附加一个属性访问器

    超级道具为超类附加属性访问器曾经想要一些语法糖来调用原型链上的函数吗? BaseClass.prototype.... // then do my own stuff here}入门安装super-prop npm install super-prop创建子类时.. var superprop = req

    Javascript 继承机制实例

    实际上,几何形状只有两种,即椭圆形(是圆形的)和多边形(具有...圆形(Circle)继承了椭圆形,因此圆形是椭圆形的子类(subclass),椭圆形是圆形的超类(superclass)。同样的,三角形(Triangle)、矩形(Rectan

    fringejs:基于原型的 JavaScript Web 应用程序框架

    这意味着对象可以直接继承其他对象,而不是子类从超类继承的经典语言,并且对象是类的实例。 许多类似的框架使用伪经典继承模式,它们试图通过创建函数的实例并使用函数的原型来继承类结构来模仿经典继承。 然而, ...

    写给大家看的面向对象编程书(第3版).[美]Matt Weisfeld(带详细书签).pdf

    1.7.1 超类和子类 16 1.7.2 抽象 16 1.7.3 is-a关系 17 1.8 多态 18 1.9 组合 20 1.9.1 抽象 21 1.9.2 has-a关系 21 1.10 小结 21 1.11 本章使用的示例代码 21 1.11.1 TestPerson示例:C#.NET 21 1.11.2 ...

    关于JavaScript中原型继承中的一点思考

    我们先看一段传统的继承代码: 代码如下: //定义超类 function Father(){ this.name = “父亲”; } Father.prototype.theSuperValue = [“NO1″,”NO2”]; //定义子类 function Child(){ } //实现继承 Child....

    JavaScript 继承使用分析

    深入学习javascript继承之前,先了解下面的几个概念: 父类:被继承的类 子类:由继承得来的类 超类:也就是父类 抽象类:一般不用来实例化的类,它的用途是用来给其他类继承. 基类:提供给其他类可以继承的类 派生类:由基类...

    pillar:建立在 Backbone 上的扩展层,与个人项目一起开发

    一个建立在 Backbone.js 上的扩展层, pillar提供了处理视图和模板的扩展功能。 观看次数 Struts的主要功能是实现视图的完全扩展,通常在主干中扩展视图不会将子类的事件与超类的事件合并。 初始化函数堆栈也没有。 ...

    rubric:Ruby 的 D3 可视化

    这是对 D3、JavaScript 和数据可视化的个人探索。 数据集 该数据集是 YAML、JSON 和 CSV 文件的大杂烩,它们表示核心库中 Ruby 类之间的关系。 原始信息是从并使用多个自定义rake任务进行处理。 可视化 目前,有四种...

    day019-io笔记和代码.rar

    * JS、JSP :UTF-8 * * 后台: * java :UTF-8 * * 数据库: * mysql、oracle、DB2 :UTF-8 * * 开发工具:UTF-8 * 2. 文本文件用统一的字符集 且用...

    mkapi:MkDocs的文档生成工具

    MkApi MkApi插件生成用于Python代码API文档。 MkApi支持两种类型的文档字符串:和 。... 文档字符串继承:子类的文档字符串可以从其超类继承参数和属性描述。 目录:将目录插入每个包,模块和类的

    javascript单元测试(上)

    对于面向对象编程,最小单元就是方法,包括基类(超类)、抽象类、或者派生类(子类)中的方法。每个理想的测试案例独立于其它案例;为测试时隔离模块,经常使用stubs、mock或fake等测试马甲程序。单元测试通常由...

    Custom-Frogger-Game

    敌人函数充当伪经典超类,在其上构建两个子类(玩家和宝石)。 Html5用于在屏幕上绘制图像并设置背景布局。 您将在下面找到为使游戏正常运行而添加的所有功能。 ####Enemy 函数已加载 用来代表敌人的图片是images/...

    class-extender:简单类继承

    类扩展器 不建议使用此模块,请改用ES6。 动机 如您所知,有很多不同的... 您可以使用上面的this._super()调用Person超类的原始init()和dance()方法来查看此内容。 安装 NodeJS: $ npm install class-extender

Global site tag (gtag.js) - Google Analytics