js中基于prototype实现继承的基本代码如下所示:
function(SubClass, SuperClass){
function F(){}
//
F.prototype = SuperClass.prototype;
// 实现继承的关键,构造 prototype chain
SubClass.prototype = new F(); // 1
// 重置子类prototype对象的constructor属性为子类本身。
SubClass.prototype.constructor = SubClass;
// 设置子类的superclass属性值为父类的prototype。
SubClass.superclass = SuperClass.prototype; // 2
// 使得在子类中可以通过baseconstructor来访问父类的构造函数。
SubClass.baseconstructor = SuperClass;
}
上述代码中有两个值得关注的地方:
(1)语句1处使用了new F()的方式,这里为什么需要专门new一个F对象出来呢?首先我们来看下面的这段代码的结果:
function SP(){this.cls = "super class";}
SP.prototype.print(alert(this.cls););
function SB(){}
SB.prototype = SP.prototype
SB.prototype.print(alert("changed by subclass"));
new SP().print(); // output: changed by subclass
从结果可知SB prototype对象的改变同时影响到了SP,也即此时SB和SP是共享同一个prototype对象。这是不符合继承的本意的。这里如果将
SB.prototype = SP.prototype
更改为:
SB.prototype = new SP()
则可以避免此问题。这也是代码1处使用了new F() 而不是F.prototype的原因。
这里还有一个疑问就是F在这里具体作用是什么?为什么需要添加F,而不是直接使用new SuperClass()
?
先看下面这段代码:
function SP(){this.cls = "super class";}
SP.prototype.print(alert(this.cls););
function SB(){}
SB.prototype = new SP();
new SB().print(); // super class
function F(){}
F.prototype = SP.prototype;
SB.prototype = new F();
new SB().print(); // undefined
代码中两次执行print函数打印出的结果分别是“super class” 和 undefined。也即第二次执行此函数时SB对象中不存在cls属性,这正是添加一个空的F函数的作用。它可以避免在子类SB中获得得到在父类SP函数体中定义的属性(this.xxx)。
(2)语句2处SubClass.superclass为SuperClass.prototype,而不是SuperClass本身。关于这一点的说明,引用 http://bbs.51js.com/viewthread.php?tid=72688&page=1&extra=#pid556697
上某位网友的观点:
原型链继承 subclass就是通过prototype的技巧性处理来继承superclass的 这本身是一个逐级向上的递归过程 所以指定superclass指定到superclass的prototype比较合理,而且以后调用也方便 只需要subclass.superclass.method.call 如果像你那样指定的话就需要subclass.superclass.prototype.method.call 反而更复杂了 。
subclass.superclass.call(this) 的方式没有subclass.superclass.constructor.call(this)的方式直观
而且构造函数constructor我感觉也是显示调用比较好,风格比较一致,而且少点潜规则也更容易看懂吧,没必要学java的那种方式,而且如果superclass没有构造函数的话 按照ext的方式会逐级向更上层的父类调用,直到最顶端。
Ext中的继承也是基于prototype chain的方式来实现的,在 http://www.iteye.com/topic/195409
有对其继承方法实现的详细解析。但是,其中有一处代码一直未弄懂其作用:
if(spp.constructor == Object.prototype.constructor){
spp.constructor=sp;
}
这一代码中,if条件成立时有两种可能:(1)sp本身就是Object;(2)函数对象在创建时,其prototype对象的constructor属性值总是指向函数对象本身。因此另一种可能就是sp显示改变了其prototype对象,而新对象的constructor属性值指向的是Object。第1种情况处理没有任何意义,因为此时spp.constructor一定等于sp;那么只可能是第二种情况。一个令人费解的问题是"为什么要到有子类继承时才重置父类protoype对象constructor的值,而不是在显示改变其prototype对象时就设置"。为什么这里需要重置constructor的值呢?结合前后代码来看:
spp = sp.prototype;
sb.superclass=spp;
if(spp.constructor == Object.prototype.constructor){
spp.constructor=sp;
}
同上文中关于语句2处设置子类superclass一样,此处sb的superclass属性设置为了spp,其父类sp的prototype对象。此时,若想访问到父类本身,就只能通过spp的constructor属性。因此,才需要对constructor属性进行判断,将其重置为父类sp。也即,加入此语句的原因是为了能够保证在子类中正确调用到父类的构造函数
,而不是Object。
分享到:
相关推荐
javascript的prototype继承
我们已经在第一章中使用prototype属性模拟类和继承的实现。 prototype属性本质上还是一个JavaScript对象。 并且每个函数都有一个默认的prototype属性。 如果这个函数被用在创建自定义对象的场景中,我们称这个函数为...
主要介绍了JavaScript使用prototype属性实现继承操作,结合实例形式详细分析了JavaScript使用prototype属性实现继承的相关原理、实现方法与操作注意事项,需要的朋友可以参考下
JavaScriptprototype的深度探索不是原型继承那么简单.pdf
javascript原型继承,prototype的使用,可以像java一样继承
构造函数定义对象+prototype继承的实现,含CSS样式
不错的一篇关于javascript-prototype继承
详解JavaScript中基于原型prototype的继承特性_.docx
NULL 博文链接:https://liujunhg.iteye.com/blog/1069419
javascript的prototype原型简单介绍: prototype原型是javascript中特别重要的概念,属于必须要掌握,如果没有良好的掌握的话,进一步用好或者学好js基本是不可能的实现的事情,并且此概念稍有难度,可能对于初次接触...
每个函数都有一个prototype属性,这个属性是指向一个对象的引用,这个对象称为原型对象,原型对象包含函数实例共享的方法和属性,也就是说将函数用作构造函数调用(使用new操作符调用)的时候,新创建的对象会从原型...
Javascript中关于prototype属性实现继承的原理图
主要介绍了JavaScript使用prototype原型实现的封装继承多态,涉及javascript prototype与面向对象程序设计相关操作技巧,需要的朋友可以参考下
主要介绍了JavaScript不使用prototype和new实现继承机制的相关资料,需要的朋友可以参考下
一、什么是JavaScript中对象的prototype属性 JavaScript中对象的prototype属性,是用来返回对象类型原型的引用的。我们使用prototype属性提供对象的类的一组基本功能。并且对象的新实例会”继承”赋予该对象原型的...
本文实例讲述了javascript基于prototype实现类似OOP继承的方法。分享给大家供大家参考,具体如下: 这里要说明的是,公有属性(使用this.修饰符)可以被覆盖,私有属性(使用var 修饰符)不能被覆盖 子类不能访问父类...
主要介绍了javascript使用prototype完成单继承的方法及示例代码,有需要的小伙伴参考下
JavaScript中实现继承最简单的方式就是使用原型链,将子类型的原型指向父类型的实例即可,即“子类型.prototype = new 父类型();”,实现方法如下: // 为父类型创建构造函数 function SuperType() { thi
只有构造器才具有prototype属性,原型链继承就是创建一个新的指针,指向构造器的prototype属性。 prototype属性之所以特别,是因为javascript时读取属性时的遍历机制决定的。本质上它就是一个普通的指针。 构造器...