1. 原型链继承
function Father(msg) {
this.msg = msg;
}
Father.prototype.print = function () {
console.log(this.msg);
};
function Son(name) {
this.name = name;
}
Son.prototype = new Father("消息");
const s1 = new Son("name1");
const s2 = new Son("name2");
s1.print(); // 消息
s2.__proto__.msg = "s2修改后的msg";
s1.print(); // s2修改后的msg
问题:
无法向父类构造函数传参
实例都是指向的同一个原型链,更改了某一个实例的原型链属性就会影响各个实例
2. 借用构造函数继承
function Father(msg) {
this.msg = msg;
}
function Son(name, msg) {
Father.call(this, msg);
this.name = name;
}
const s = new Son("名字", "信息");
console.log(s.name, s.msg);
可以传参,改了指向,不会出现属性共用。
问题:
只能在构造函数中定义函数
只能继承父类实例属性
指向改为了子类,不是父类的实例
3. 组合式继承
function Father(msg) {
this.msg = msg;
}
Father.prototype.print = function () {
console.log(this.msg);
};
function Son(name, msg) {
// 第二次构造
Father.call(this, msg);
this.name = name;
}
// 第一次构造
Son.prototype = new Father();
Son.prototype.constructor = Son;
原型链继承+借用构造函数继承。
继承父类原型链,更改构造函数为子类,可以传参。
问题:
调用了2次创建实例
构造函数不指向父类
4. 寄生式继承
function object(o) {
function F() {}
F.prototype = o;
return new F();
}
function Father(msg) {
this.msg = msg;
}
function Son(name, msg) {
const father = object(new Father(msg));
father.name = name;
father.print = function () {
console.log(this.msg);
};
return father;
}
用父类创建实例并添加属性、方法
问题:
无法继承多个父类
只调用了父类,不是子类的实例
5. 组合寄生式继承
function Father(msg) {
this.msg = msg;
}
function Father2(msg) {
this.msg = msg;
}
Father.prototype.print = function () {
console.log(this.msg);
};
function Son(name, msg, msg2) {
Father.call(this, msg); // 继承父类
Father2.call(this, msg2); // 继承多个父类
this.name = name;
}
// 浅拷贝继承父类的方法,避免直接引用
Son.prototype = Object.create(Father.prototype, {
constructor: {
value: Son, // 构造函数指向子类
},
});
Son.prototype.say = function () {
console.log("son say");
};
用Object.create来实现浅拷贝,
目前最优方法,先浅拷贝父类的原型链,再将原型链中的构造函数指向子类,再赋值给子类的原型。子类通过借用构造函数来传参和父类的多继承。
6. extends
基于组合寄生式继承