- 原型链继承 (将超类(父类)的实例对象 赋值给 子类的原型对象)
- 优点: 简单易于实现
- 缺点
- 不可多继承
- 子类不能向超类传递参数
- 子类实例成员之间共享父类的属性,如果该属性是引用数据类型,子类实例成员之间将相互影响。
- 子类若要声明自己的原型方法需在继承之后
function SuperClass() {
this.name = "super";
this.list = []; //被共享,其中一个子类成员push,其他子类实例成员拿到的list 也会随之变化
}
SuperClass.prototype.say = function () {
console.log("wo shi super");
};
SuperClass.prototype.push = function (p) {
this.list.push(p);
};
function SubClass() {
this.name = "sub";
}
SubClass.prototype.say = function () {
console.log("wo shi sub");
};
SubClass.prototype = new SuperClass(); //继承父类的实例对象
SubClass.prototype.print = function () {
console.log("print sub");
};
const instance1 = new SubClass();
instance1.say(); // wo shi super
instance1.push("instance1"); //将影响其他的子类实例成员的list属性
instance1.print();
const instance2 = new SubClass();
console.log(instance2.list); // ["instance1"];
- 借用构造函数继承
(调用父类的构造函数)
- 优点
- 可以多继承
- 子类可以向超类传递参数
- 继承引用类型的属性子类实例成员之间没有影响
- 缺点
- 不能继承原型链上的属性和方法
- 方法定义在构造函数内,不能被复用(每个子类去继承都是新的函数)
function SuperClass(age) {
this.name = "super";
this.age = age;
// 不能被复用
this.say = function () {
console.log("wo shi super");
};
}
//不能被继承
SuperClass.prototype.print = function () {
console.log("wo shi super");
};
function SubClass() {
SuperClass.call(this, 123);
}
const instance = new SubClass();
console.log(instance.age);
- 原型式继承
(本质是对象的浅复制)
- 优点:简单易于实现
- 缺点: 同原型链继承一样,超类引用类型被子类共享
function CloneObj(o) {
const Fn = function () {};
Fn.prototype = o;
return new Fn();
}
const superObj = {
sex: "男",
things: ["money", "house"]
};
const sub1 = CloneObj(superObj);
const sub2 = CloneObj(superObj);
sub1.things.push("car"); //将影响其他子类的things属性
console.log(sub2.things); // ["money", "house", "car"]
上面的cloneObj 函数本质上对传入的对象进行了一次浅复制,在传入一个参数的情况下,作用于Object.create()类似.<https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Object/create>
4. 组合继承
(原型链继承 + 借用超类构造函数)
- 优点
- 父类原型方法可以实现复用
- 超类引用类型属性共享 子类间不会相互影响
- 缺点
- 构造函数被调用两次,创建了俩两超类实例
function SuperClass(age) {
this.name = "super";
this.age = age;
}
SuperClass.prototype.say = function () {
console.log("wo shi super");
};
function SubClass() {
SuperClass.call(this, 123);
}
SubClass.prototype = new SuperClass();
SubClass.prototype.constructor = SubClass; //重新添加构造函数指向
const instance = new SubClass();
- 寄生式组合继承
(目前最完美的继承实现方式)
function SuperClass(age) {
this.name = "super";
this.age = age;
}
SuperClass.prototype.say = function () {
console.log("wo shi super");
};
function SubClass() {
SuperClass.call(this, 123);
}
//继承函数
function inherit(sup, sub) {
const Fn = function () {};
Fn.prototype = sup.prototype;
sub.prototype = new Fn();
sub.prototype.constructor = sub;
// sub.prototype = Object.create(sup.prototype)
}
inherit(SuperClass, SubClass);
const instance = new SubClass();
- es6继承
class SuperClass {
constructor(name = "super", age = 123) {
this.name = name;
this.age = age;
}
say() {
console.log(`wo shi ${this.name}, age is ${this.age}`);
}
}
class SubClass extends SuperClass {
constructor(name, age) {
super(name, age); //继承超类属性并传递参数
}
say() {
super.say(); //继承超类方法
}
}
class SubClass2 extends SuperClass {
constructor(name, age) {
super(name, age); //继承超类属性并传递参数
}
say() {
super.say(); //继承超类方法
}
}
const instance1 = new SubClass("sub1", 345);
const instance2 = new SubClass2("sub2", 456);
instance1.say(); // wo shi sub, age is 345
instance2.say(); // wo shi sub2, age is 456
console.log(instance1.say == instance2.say); // false