一.构造函数继承
- 构造函数继承的基本思路是在子类型的构造函数中,调用要继承的构造函数,具体实现如下:
function Parent() {
this.name = ["heyushuo", "kebi"];
}
function Child() {
Parent.call(this);
// 或者 Parent.apply(this);
}
var Person1 = new Child();
Person1.name.push("kuli");
console.log(Person1.name); //["heyushuo", "kebi","kuli"];
var Person2 = new Child();
console.log(Person2.name); //["heyushuo", "kebi"];
// 通过上边的两个打印,Child的两个实例继承的name属性不会互相影响
// 因为,创建Child实例的环境下调用Parent构造函数,这样可以使得每个实例都会具有自己的name属性,所以两个不会互相影响
2. 优点(可以传递参数)
function Parent(name) {
this.name = name;
}
function Child() {
Parent.call(this, "heyushuo");
//或者Parent.apply(this, ["heyushuo"]);
}
var Person = new Child();
console.log(Person.name); //heyushuo
// 需要注意的:为了确保Parent构造函数不会重写子类型的属性,需要在Parent.call(this)之后在定义子类型中的属性
3.构造函数的缺点
因为方法和属性只能写在构造函数中,因此不能实现函数复用 只能继承父类的实例属性和方法,不能继承原型属性/方法 (原型中定义的方法和属性对于子类是不可见的)
二.组合继承(原型链和构造函数组合式继承)
通俗来讲就是用原型链实现对原型属性和方法的继承,用借用构造函数继承来实现对实例属性的继承。
function Parent(name) {
this.name = name;
this.newArr = ["red", "blue", "green"];
}
Parent.prototype.sayName = function() {
console.log(this.name);
};
function Child(name) {
Parent.call(this, name);
this.age = 26;
}
Child.prototype = new Parent();
//重写Child.prototype的constructor属性,使其执行自己的构造函数Child
Child.prototype.constructor = Child;
Child.prototype.sayAge = function() {
console.log(this.age);
};
var Person1 = new Child("heyushuo");
console.log(Person1);
Person1.newArr.push("yellow");
console.log(Person.newArr); //["red", "blue", "green","yellow"]
Person.sayName(); //heyushuo
var Person2 = new Child("kebi");
console.log(Person2.newArr); //["red", "blue", "green"]
Person.sayName(); //kebi
通过一张图来看一下:
总结
- 组合式继承避免了原型链和构造函数的缺陷,融合了他们的有点,成为最常用的继承模式
- 组合式继承有一个缺点, 如上图可以看出, 创建的实例和原型上存在两份相同的属性即(name 和 newArr);