- 浏览: 336108 次
- 性别:
- 来自: 北京
文章分类
最新评论
先引一段原文,可略过..
这段话前半部分描述了一个重要信息: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为例):
完工了,Man已经成为了Person的子类。
当然,这样写虽然能达到效果,但可能不符合“标准”,那就换成标准的:
这就是“标准”的做法。当然也可以突发奇想,让Man只继承Person.prototype的属性,而不包括Person的实例属性。
总之,Man是谁的子类就看Man.prototype是由谁的构造函数初始化的。只要把握了这点,继承关系可以随心所欲的构造。
但注意,试图通过把子类的prototype的constructor设为父类的构造函数是不行的。因为prototype并没有被父类的构造函数初始化,它还是由Object()初始化,只是它的constructor属性值改为父类了。 当子类实例访问"父类"prototype内的同名方法时,并不会到"父类"里查找,而是查找Object及Object.prototype。
另外说说call的作用(apply也一样):
调用Person的构造函数Person,call的第一个参数是绑定Person函数的临时对象,后面的参数是要传给Person的。此例中this即Man实例绑定了Person函数,并调用它。然后person方法内的this指向的就不再是Person实例了,而是Man实例,最终效果就好像它是Man的构造函数一样:所有Man实例就都有了Person实例的属性。
.....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实例的属性。
发表评论
-
涉及页面展示尽量少用js
2012-07-04 10:42 1254用js操作DOM元素会引起页面频繁的reflow和 ... -
inline Element相互之间多出几像素的空白
2011-10-19 05:17 2356若干个行内元素并排排列,margin,padding都设成0了 ... -
兼容各浏览器盒子模型
2011-09-24 23:36 5768各浏览器盒模型的 ... -
获取鼠标相对位置
2011-09-20 10:48 2465获取鼠标相对于html的位置: function mo ... -
判断日期格式
2011-08-17 09:34 1068var startTime = "2011-03-3 ... -
JS简易拖拽效果
2011-07-31 22:48 6862模仿《javascript权威指南》写了个简易拖拽程序,麻雀虽 ... -
IE事件注册相关的内存泄露总结
2011-06-03 17:28 1410经过一上午的艰苦试验验证,得出如下结论: 1、将元 ... -
假的,全是假的!!(更新)
2010-10-11 21:31 1461<meta http-equiv="P ... -
IE内存泄露与无法回收研究小结(持续增加中)
2010-09-21 16:19 6234一、内存泄露 之前 ... -
javascript父、子页面交互小结
2010-06-04 12:05 8498帧用来存放子页面 ... -
获取子窗口中使用jQuery.data()设置的参数
2010-04-13 17:49 5543假设在iframe子窗口中设置了$('#mydata') ... -
《JavaScript The Definitive Guide 5th》闭包读后总结
2010-03-24 10:51 1352JavaScript functions are a comb ... -
"position:relative"在IE中的Bug
2010-03-22 09:29 6009请看下图: 即子元素过高导致父元素出现滚动条时,它并不会像预 ... -
JS没有"块作用域"
2010-03-17 16:01 1391没别的意思,只是记下来而已,这在犀牛书上是明明白白地写着 ... -
jquery的data函数
2010-02-03 18:45 3309今天试着使用了下这个函数,真是万事开头难,碰了个灰头土脸, ... -
使用设计模式的目的
2009-12-09 10:24 2019为什么要用设计模式?在生搬硬套了策略模式之后产生了这种疑 ... -
jquery 整体感觉
2009-11-12 10:34 1306用了一段时间后,觉得它和Ext虽然有很大不同,但如果稍微 ... -
jquery的each函数中的break和continue功能
2009-10-20 17:06 27330each函数不能使用break和continue关键字,替代方 ... -
移除JS数组指定位置的元素
2009-10-15 10:34 18884JavaScript中splice函数方法是从一个数组 ... -
JQuery动态添加Select的Option元素
2009-09-21 10:02 12570代码贴上: var selector=$('<s ...
相关推荐
javascript闭包子类超类简介,有利于初学者对该技术的理解。
我们将会解释如何模拟继承及其超类与子类之间关系的形式。原型是理解继承概念的关键, 我们将会教你如何建立原型, 如何检测一个对象是否是另外一个对象的原型, 及其 JavaScript 的模型与Java 面向对象编程之间的区别...
在JavaScript中的继承的实质就是子代可以拥有父代公开的一些属性和方法,在js编程时,我们一般将相同的属性放到父类中,然后在子类定义自己独特的属性,这样的好处是减少代码重复。继承是面向对象的基础,是代码重用...
选定基类后,就可以创建它的子类了。...子类还可添加超类中没有的新属性和方法,也可以覆盖超类中的属性和方法。 4.2.1 继承的方式 和其他功能一样,ECMAScript中实现继承的方式不止一种。这是因为JavaScr
Particle超类和Oddball子类。 所有粒子必须存储在超类类型的单个数组中。 确保您没有不必要地在Oddball子类中重复继承的变量和函数。 您的Oddball子类只需要包含一个构造函数以及void move()和/或void show()以便...
超级道具为超类附加属性访问器曾经想要一些语法糖来调用原型链上的函数吗? BaseClass.prototype.... // then do my own stuff here}入门安装super-prop npm install super-prop创建子类时.. var superprop = req
实际上,几何形状只有两种,即椭圆形(是圆形的)和多边形(具有...圆形(Circle)继承了椭圆形,因此圆形是椭圆形的子类(subclass),椭圆形是圆形的超类(superclass)。同样的,三角形(Triangle)、矩形(Rectan
这意味着对象可以直接继承其他对象,而不是子类从超类继承的经典语言,并且对象是类的实例。 许多类似的框架使用伪经典继承模式,它们试图通过创建函数的实例并使用函数的原型来继承类结构来模仿经典继承。 然而, ...
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 ...
我们先看一段传统的继承代码: 代码如下: //定义超类 function Father(){ this.name = “父亲”; } Father.prototype.theSuperValue = [“NO1″,”NO2”]; //定义子类 function Child(){ } //实现继承 Child....
深入学习javascript继承之前,先了解下面的几个概念: 父类:被继承的类 子类:由继承得来的类 超类:也就是父类 抽象类:一般不用来实例化的类,它的用途是用来给其他类继承. 基类:提供给其他类可以继承的类 派生类:由基类...
一个建立在 Backbone.js 上的扩展层, pillar提供了处理视图和模板的扩展功能。 观看次数 Struts的主要功能是实现视图的完全扩展,通常在主干中扩展视图不会将子类的事件与超类的事件合并。 初始化函数堆栈也没有。 ...
这是对 D3、JavaScript 和数据可视化的个人探索。 数据集 该数据集是 YAML、JSON 和 CSV 文件的大杂烩,它们表示核心库中 Ruby 类之间的关系。 原始信息是从并使用多个自定义rake任务进行处理。 可视化 目前,有四种...
* JS、JSP :UTF-8 * * 后台: * java :UTF-8 * * 数据库: * mysql、oracle、DB2 :UTF-8 * * 开发工具:UTF-8 * 2. 文本文件用统一的字符集 且用...
MkApi MkApi插件生成用于Python代码API文档。 MkApi支持两种类型的文档字符串:和 。... 文档字符串继承:子类的文档字符串可以从其超类继承参数和属性描述。 目录:将目录插入每个包,模块和类的
对于面向对象编程,最小单元就是方法,包括基类(超类)、抽象类、或者派生类(子类)中的方法。每个理想的测试案例独立于其它案例;为测试时隔离模块,经常使用stubs、mock或fake等测试马甲程序。单元测试通常由...
敌人函数充当伪经典超类,在其上构建两个子类(玩家和宝石)。 Html5用于在屏幕上绘制图像并设置背景布局。 您将在下面找到为使游戏正常运行而添加的所有功能。 ####Enemy 函数已加载 用来代表敌人的图片是images/...
类扩展器 不建议使用此模块,请改用ES6。 动机 如您所知,有很多不同的... 您可以使用上面的this._super()调用Person超类的原始init()和dance()方法来查看此内容。 安装 NodeJS: $ npm install class-extender