js 实现继承
原型链继承
通过让子类的原型对象指向父类的实例来实现继承。子类实例可以通过原型链访问父类的属性和方法。
function Parent() {
this.name = 'parent';
}
Parent.prototype.sayName = function() {
console.log(this.name);
};
function Child() {}
Child.prototype = new Parent(); // 关键步骤
const child = new Child();
child.sayName(); // 'parent'
缺点:所有子类实例共享同一个父类实例的属性,修改引用类型属性会影响其他实例。
构造函数继承
在子类构造函数中调用父类构造函数,使用call或apply方法改变this指向。
function Parent(name) {
this.name = name;
}
function Child(name) {
Parent.call(this, name); // 关键步骤
}
const child = new Child('child');
console.log(child.name); // 'child'
缺点:无法继承父类原型上的方法和属性。
组合继承
结合原型链继承和构造函数继承,既通过构造函数继承实例属性,又通过原型链继承原型方法。
function Parent(name) {
this.name = name;
}
Parent.prototype.sayName = function() {
console.log(this.name);
};
function Child(name) {
Parent.call(this, name); // 继承实例属性
}
Child.prototype = new Parent(); // 继承原型方法
const child = new Child('child');
child.sayName(); // 'child'
缺点:调用了两次父类构造函数,子类原型上会有多余的父类实例属性。
寄生组合继承
目前最理想的继承方式,通过Object.create创建父类原型的副本作为子类原型。
function Parent(name) {
this.name = name;
}
Parent.prototype.sayName = function() {
console.log(this.name);
};
function Child(name) {
Parent.call(this, name);
}
Child.prototype = Object.create(Parent.prototype); // 关键步骤
Child.prototype.constructor = Child; // 修复构造函数指向
const child = new Child('child');
child.sayName(); // 'child'
ES6类继承
使用class和extends语法糖实现继承,本质仍是基于原型链。

class Parent {
constructor(name) {
this.name = name;
}
sayName() {
console.log(this.name);
}
}
class Child extends Parent {
constructor(name) {
super(name); // 必须调用super
}
}
const child = new Child('child');
child.sayName(); // 'child'
ES6类继承解决了传统继承方式的多个问题,是最推荐的继承实现方式。






