原生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"
ES5实现类语法糖
通过立即执行函数返回构造函数,模拟class的extend效果,底层仍使用寄生组合继承。
var Animal = (function() {
function Animal(name) {
this.name = name;
}
Animal.prototype.sayName = function() {
console.log(this.name);
};
return Animal;
})();
var Dog = (function(_super) {
function Dog(name) {
_super.call(this, name);
}
Dog.prototype = Object.create(_super.prototype);
Dog.prototype.constructor = Dog;
Dog.prototype.bark = function() {
console.log('Woof!');
};
return Dog;
})(Animal);
var dog = new Dog('Buddy');
dog.sayName(); // 输出 "Buddy"
dog.bark(); // 输出 "Woof!"






