对象间的“继承”五种方法:
一、构造函数绑定
最简单的方法,使用call或apply方法,将父对象的构造函数绑定在子对象上,即在子对象构造函数中加一行:
范例:
function Animal() {
this.species = "动物";
}
function Cat(_name, _color) {
Animal.apply(this, arguments);
this.name = _name;
this.color = _color;
}
var cat = new Cat("Andy", "White");
console.log(cat.species); // 动物
二、prototype模式
使得Cat的prototype对象,指向一个Animal实例,那么所有Cat的实例,就能继承Animal
范例:
Cat.prototype = new Animal();
Cat.prototype.constructor = Cat;
var cat = new Cat("Andy", "Black");
console.log(cat.species);
说明:
代码第一行(Cat.prototype = new Animal()),将Cat的prototype对象指向一个Animal实例; 它相当于完全删除了原prototype对象的引用值,然后赋予一个新值
代码第二行(Cat.prototype.constructor = Cat):任何一个prototype对象都有一个constructor属性,指向它的构造函数。如果没有第一行代码(Cat.prototype = new Animal()),Cat.prototype.constructor 是指向Cat的;加入这一行后,Cat.prototype.constructor指向Animal;
更重要的是,每一个对象实例也有一个constructor属性,默认指向prototype对象的constructor属性;
altert(cat.constructor == Cat.prototype.constructor) // true
三、直接继承prototype
对prototype模式的改进;由于Animal对象中,不变的属性都直接写入Animal.prototype对象中,所以,可以让Cat()调岗Animal(),直接继承Animal.prototype对象
范例:
function Animal() {};
Animal.prototype.species = "动物";
//将Cat的prototype对象,指向Animal的prototype对象,就完成继承工作
Cat.prototype = Animal.prototype;
Cat.prototype.constructor = Cat; //修改了对象的prototype引用,prototype对象的constructor属性也必须修正
缺点:
Cat.prototype和Animal.prototype都指向了同一个对象,那么任何对Cat.prototype的修改,都会反映到Animal.prototype
代码:Cat.prototype.constructor = Cat,这一句实际上把Animal.prototype对象的constructor属性也改掉了
console.log(Animal.prototype.constructor); // Cat
四、利用空对象作为中介
范例:
var F= function() {};
F.prototype = Animal.prototype;
Cat.prototype = new F();
Cat.prototype.constructor = Cat;
解释:
F 是空对象,所以 几乎不占内存;此时,修改Cat的prototype对象,不会影响到Animal的prototype对象
console.log(Animal.prototype.constructor); // Animal
再次将上述进行封装:
function extend(childObj, parentObj) {
var F = function() {};
F.prototype = parentObj.prototype;
childObj.prototype = new F();
childObj.prototype.constructor = childObj;
childObj.uber = parentObj.prototype;
}
注:extend()方法,就是YUI库如何实现继承的方法
使用:
extend(Cat, Animal);
var cat = new Cat("Andy", "Black");
console.log(cat.species); //动物
另外,函数体最后一行说明(childObj.uber = parentObj.prototype), 意思是为子对象设置一个uber属性,此属性直接指向父对象的prototype对象(uber, 德语词,意思是“向上”、“上一层”),放在此处,只是为了实现继承的完备性,纯属备用性质。
五、拷贝继承
介绍:把父对象的所有属性和方法,拷贝进子对象,从而实现拷贝进程
实现:
首先:把Animal所有不变的属性,放到prototype对象上
function Animal() {};
Animal.prototype.species = "动物";
再者,编写新函数,实现属性拷贝目的
function extend(Child, Parent) {
var p = Parent.prototype;
var c = Child.prototype;
for (var index in p) {
c[index] = p[index];
}
c.uber = p;
}
使用:
extend(Cat, Animal);
var cat = new Cat("Andy", "Black");
console.log(cat.species); // 动物