最近在看js高级程序设计,里面讲了有2种推荐的继承方式,一种是组合(构造函数+冒充)继承:
function SuperType(name){
this.name = name;
this.colors = ["red", "blue", "green"];
}
SuperType.prototype.sayName = function(){
alert(this.name);
};
function SubType(name, age){
SuperType.call(this, name); //第二次调用 SuperType()
this.age = age;
}
SubType.prototype = new SuperType(); //第一次调用 SuperType()
SubType.prototype.constructor = SubType;
SubType.prototype.sayAge = function(){
alert(this.age);
};
另外一种是组合寄生式继承:
function object(o){
function F(){}
F.prototype = o;
return new F();
}
function inheritPrototype(subType, superType){
var prototype = object(superType.prototype); //创建对象
prototype.constructor = subType; //增强对象
subType.prototype = prototype; //指定对象
}
function SuperType(name){
this.name = name;
this.colors = ["red", "blue", "green"];
}
SuperType.prototype.sayName = function(){
alert(this.name);
};
function SubType(name, age){
SuperType.call(this, name);
this.age = age;
}
inheritPrototype(SubType, SuperType);
SubType.prototype.sayAge = function(){
alert(this.age);
};
上面讲到:组合继承是 JavaScript 最常用的继承模式有它的不足,就是无论什么情况下,都会调用两次超类型构造函数。
下面那种方式,虽然没有调用2次构造函数,但是却执行了多次函数调用(inheritPrototype里面调用了object,object里面调用了new F() ),那为什么又普遍认为,下面这种方式,比上面这种方式要好呢?
伊谢尔伦2017-04-10 16:55:57
两种方式谁好谁坏不在于调用父构造函数的次数!而是第二种方式得到的
SubType.prototype
比第一种方式得到的要干净!
下面细说:
其实第二种方式虽然看起来调了两次父构造函数。实际上,假设你实例化了N个子类的对象的话:第一种方式调用父构造函数N+1次,第二种方式调用构造函数N次。所以是N+1和N的区别,不是2N和N的区别。这个区别可以忽略。
关键在于两种方式获得SubType.prototype
的方法不同!
第一种方式,是通过new父类构造函数得到的,而且new的时候不带参数(当然根本没法提供参数),结果得到的SubType.prototype
里面有不需要的属性,例如name和colors。这些属性在继承链中是多余的!而且由于不带参数,谁知道得到的是什么鬼?这很容易污染继承链。
第二种方式,是通过new一个空函数F得到的,这样得到的SubType.prototype
是非常干净的,相当于一个{}对象那样干净。
怪我咯2017-04-10 16:55:57
调用函数本身造成的资源损耗并不严重,相对于难以预估的类构造函数,这两个函数的体积和计算量都小的几乎可以忽略不计。
类比一下,构造函数可能相当于一辆坦克,这俩函数相当于两把菜刀,你觉得哪个战斗力高。
PHP中文网2017-04-10 16:55:57
组合(构造函数+冒充)继承时,由于
SubType.prototype = new SuperType(); //第一次调用 SuperType()
导致SubType.prototype上面有了SuperType的name和colors属性,这两个属性实际上是多余没有意义的,因为
function SubType(name, age){
SuperType.call(this, name); //第二次调用 SuperType()
...
}
所以var newObj = new SubType的时候,新的实例的name和colors已经在第二次调用SuperType的时候放到了this上。
而组合寄生式继承就解决了这个问题。