JS无法像其他高级语言那样通过extend直接实现继承。只通过一定方式来实现继承机制。常见的几种实现继承的方式有:
- 对象冒充
- call/apply方法
- 原型链(prototype chain)
- 混合方式(call/apply+prototype chain)
1. 对象冒充
父类:
1 2 3 4
| function superClass(name){ this.name=name; this.type='superClass'; }
|
子类:
1 2 3 4 5 6 7 8
| function subClass(name) { this.extends= superClass; this.extends(name); delete this.extends; this.type='subClass'; }
|
这种方式的缺点有1.需额外添加一个属性;2.无法使用父级原型的拥有的属性
注意:子类的独自拥有的属性应该放在最后,以防止父类的属性覆盖了
对象冒充可以实现多重继承:
1 2 3 4 5 6 7 8 9
| function ClassZ() { this.newMethod = ClassX; this.newMethod(); delete this.newMethod; this.newMethod = ClassY; this.newMethod(); delete this.newMethod; }
|
2. call/apply方法
父类:
1 2 3 4
| function superClass(name){ this.name=name; this.type='superClass'; }
|
子类:
1 2 3 4 5 6
| function subClass(name){ superClass.call(this,name); this.type='subClass'; }
|
这种实现方式的缺点是无法继承来自父级原型的属性
3. 原型链(prototype chain)
父类:
1 2 3 4
| function superClass(name){ this.name=name; this.type='superClass'; }
|
子类:
1 2 3 4 5
| function subClass(){ this.type='subClass'; } subClass.prototype=new superClass; subObj=new subClass('it is subObj');
|
使用firebug打印对象subObj信息:console.dir(subObj)

程序原意将name属性设为’it is subobj’但没有起作用。这是因为要调用父类,必须在设置原型的时候调用。即subClass.prototype=new superClass(name)
但属性较多的情况下,就过于麻烦了。解决办法就是下面将讲的混合方式实现继承
在讲混合方式实现继承之前,我们先来了解一下对象继承关系和属性来源判断
子类对象既是子类的实例也是父类的实例也是Object的实例。任何应用类型默认继承了Object.所有函数的默认都是Object的实例
1 2 3
| console.log(subObj instanceof superClass)=== true console.log(subObj instanceof subClass)=== true console.log(subObj instanceof Object)=== true
|
通过过in和hasOwnPropertype能判断属性的来源
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| if(property in object){
console.log(true); }else{ console.log(false); }
if(object.hasOwnPropertype('property')){
console.log(true) }else{ console.log(false) }
if(property in object && !object.hasOwnProperty('property')){
console.log(true); }
|
如果对象的属性与其原型的属性同名,则原型的属性会被屏蔽但不会覆盖,如果delete操作后,对象的属性将使原型的属性值
1 2 3 4 5 6 7 8 9 10 11
| function superClass(){ this.name='superClass'; } function subClass(){ this.name='subClass'; } subClass.prototype=new superClass(); var sub=new subClass(); console.log(sub.name); delete sub.name; console.log(sub.name);
|
4. 混合方式(call/apply+prototype chain)
父类:
1 2 3 4 5 6
| function superClass(name) { this.type='superClass'; this.name=name; } superClass.prototype.exendInfo='i\'m parent class prototype property';
|
子类:
1 2 3 4 5
| function subClass(name){ superClass.apply(this,arguments); this.type='subClass'; } subClass.prototype=new superClass;
|
问:为什么会添加最后一句?使用superClass.apply(this,arguments);不就行了吗?
答:如果只使用superClass.apply(this.arguments)则使用父类的构造函数。但是无法继承了父类的原型属性,即extendInfo属性。
参考资料
ECMAScript继承机制实现
JavaScript面向对象简介