3. 如何实现对象的继承?
约 727 字大约 2 分钟
2025-03-12
在 JavaScript 中实现对象继承主要有以下几种方式,每种方式各有优缺点,以下是详细说明:
一、主要实现方式
1、原型链继承
通过将子类的原型对象指 向父类的实例实现继承。
缺点:
- 所有子类实例共享父类引用属性(如数组、对象)。
- 无法向父类构造函数传参。
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"
2、构造函数继承
在子类构造函数中调用父类构造函数(通过 call
/apply
)。
缺点:
- 无法继承父类原型上的方法。
- 方法需在构造函数中定义,无法复用。
function Parent(name) {
this.name = name;
}
function Child(name) {
Parent.call(this, name); // 继承父类属性
}
const child = new Child("Child");
console.log(child.name); // 输出 "Child"
3. 组合继承(原型链 + 构造函数)
结合原型链继承和构造函数继承。
缺点:
- 父类构造函数被调用两次,导致子类原型中存在冗余属性。
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(); // 继承方法
Child.prototype.constructor = Child; // 修正构造函数指向
const child = new Child("Child");
child.sayName(); // 输出 "Child"
4. 原型式继承
基于现有对象创建新对象(类似 Object.create
)。
缺点:
- 与原型链继承类似,引用类型属性会被共享。
const parent = { name: "Parent" };
const child = Object.create(parent); // 继承
console.log(child.name); // 输出 "Parent"
5. 寄生式继承
在原型式继承基础上增强对象。
缺点:
- 方法无法复用,类似构造函数继承。
function createChild(parent) {
const obj = Object.create(parent);
obj.sayName = function () {
console.log(this.name);
};
return obj;
}
const child = createChild({ name: "Parent" });
6. 寄生组合式继承(最优解)
通过空函数避免重复调用父类构造函数。
缺点:
- 只调用一次父类构造函数。
- 避免冗余属性,保持原型链完整。
function inherit(Child, Parent) {
const prototype = Object.create(Parent.prototype); // 复制父类原型
prototype.constructor = Child; // 修正构造函数
Child.prototype = prototype;
}
function Parent(name) {
this.name = name;
}
Parent.prototype.sayName = function () {
console.log(this.name);
};
function Child(name) {
Parent.call(this, name); // 继承属性
}
inherit(Child, Parent); // 继承方法
const child = new Child("Child");
child.sayName(); // 输出 "Child"
7. ES6 class
继承
使用 extends
和 super
语法糖。
缺点:
- 语法简洁,底层基于寄生组合式继承。
- 支持
super
访问父类方法。
class Parent {
constructor(name) {
this.name = name;
}
sayName() {
console.log(this.name);
}
}
class Child extends Parent {
constructor(name) {
super(name); // 调用父类构造函数
}
}
const child = new Child("Child");
child.sayName(); // 输出 "Child"
二、总结
- 推荐方式: 优先使用 ES6
class
,语法清晰且无历史包袱。 - 兼容旧环境: 使用 寄生组合式继承。
- 避免使用: 纯原型链或构造函数继承(有明显缺陷)。
理解这些模式有助于深入掌握 JavaScript 的原型机制和面向对象编程思想。
更新日志
2025/8/24 08:17
查看所有更新日志
e7112
-1于