search

Home  >  Q&A  >  body text

javascript - 关于js继承的疑问

最近在看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() ),那为什么又普遍认为,下面这种方式,比上面这种方式要好呢?

PHPzPHPz2902 days ago427

reply all(3)I'll reply

  • 伊谢尔伦

    伊谢尔伦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是非常干净的,相当于一个{}对象那样干净。

    reply
    0
  • 怪我咯

    怪我咯2017-04-10 16:55:57

    调用函数本身造成的资源损耗并不严重,相对于难以预估的类构造函数,这两个函数的体积和计算量都小的几乎可以忽略不计。

    类比一下,构造函数可能相当于一辆坦克,这俩函数相当于两把菜刀,你觉得哪个战斗力高。

    reply
    0
  • PHP中文网

    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上。

    而组合寄生式继承就解决了这个问题。

    reply
    0
  • Cancelreply