一、构造函数绑定

使用call或apply方法,将父对象的构造函数绑定在子对象上;

function Cat(name,color){
    Animal.apply(this, arguments);
    this.name = name;
    this.color = color;
  }

二、prototype模式

一个对象的protptype指向另一个对象的实例,那么这个对象的实例就继承了另一个对象;

//相当于完全删除了prototype 对象原先的值,然后赋予一个新值
Cat.prototype = new Animal();
Cat.prototype.constructor = Cat;

第二行代码相当重要。因为每个prototype都有个constructor属性指向构造函数。如代码,默认Cat.prototype.constructor指向Cat,但被我们改成了Animal;带来的影响是Cat的所有实例的constructor继承了Cat.prototype.constructor的指向(也就是Animal!)继承链全乱了!所以需要我们改成默认值。

三、直接继承prototype

这种方法比上一种方法效率高,使用内存更少

Cat.prototype = Animal.prototype;
Cat.prototype.constructor = Cat;

这种方法也存在缺点,实际上把Animal.prototype对象的constructor属性也改掉了;

alert(Animal.prototype.constructor); // Cat

四、更好的选择,利用空对象为中介继承

 var F = function(){};
 F.prototype = Animal.prototype;
 Cat.prototype = new F();
 Cat.prototype.constructor = Cat;

因为F是一个空对象,几乎不占用内容,我们再修改Cat.prototype对象, 就不会影响到 Animal.protptype的对象。

alert(Animal.prototype.constructor); // Animal

上面的代码可以封装为一个函数,调用使用;

function extend(Child, Parent) {
    var F = function(){};
    F.prototype = Parent.prototype;
    Child.prototype = new F();
    Child.prototype.constructor = Child;
    Child.uber = Parent.prototype;
  }

调用的时候

extend(Cat,Animal);
var cat1 = new Cat("大毛","黄色");
alert(cat1.species); // 动物

这个extend函数,就是YUI库如何实现继承的方法。另外,说明一点,函数体最后一行。

Child.uber = Parent.prototype;

uber是一个德语词,意思是”向上”、”上一层”。)这等于在子对象上打开一条通道,可以直接调用父对象的方法。这一行放在这里,只是为了实现继承的完备性,纯属备用性质。

五、拷贝继承

把父对象的所有属性和方法,拷贝进子对象,实现继承。

function extend2(Child, Parent) {
    var p = Parent.prototype;
    var c = Child.prototype;
    for (var i in p) {
      c[i] = p[i];
      }
    c.uber = p;
  }