在 JavaScript 中,实现继承的方法有多种,以下是一些常见的实现方式:
- 原型链继承
这是 JavaScript 中最常用的继承方式,它基于原型链的查找机制实现。
javascript
function Parent() {
this.name = 'parent';
}
Parent.prototype.sayHello = function() {
console.log('Hello from Parent');
}
function Child() {
this.type = 'child';
}
// 关键步骤:将 Child 的原型指向 Parent 的实例
Child.prototype = new Parent();
var child = new Child();
console.log(child.name); // 'parent'
child.sayHello(); // 'Hello from Parent'
但是,原型链继承有一个问题,那就是所有的实例都会共享原型上的属性,这可能会在某些情况下引发问题。
- 借用构造函数(伪经典继承)
通过调用父类构造函数,增强子类实例,将父类的属性添加到子类实例上。
javascript
function Parent() {
this.name = 'parent';
}
function Child() {
// 关键步骤:调用 Parent 构造函数
Parent.call(this);
this.type = 'child';
}
var child = new Child();
console.log(child.name); // 'parent'
这种方式可以解决原型链继承的问题,但是方法都在构造函数中定义,每次创建实例都会生成一次方法,方法复用就无从谈起了。
- 组合继承
将原型链继承和借用构造函数的技术组合到一块,从而发挥二者之长的一种继承模式。
javascript
function Parent() {
this.name = 'parent';
}
Parent.prototype.sayHello = function() {
console.log('Hello from Parent');
}
function Child() {
// 借用构造函数
Parent.call(this);
this.type = 'child';
}
// 原型链继承
Child.prototype = new Parent();
Child.prototype.constructor = Child;
var child = new Child();
console.log(child.name); // 'parent'
child.sayHello(); // 'Hello from Parent'
这种方式既可以实现在子类构造函数中向父类构造函数传参,又可实现函数复用,因此是 JavaScript 中最常用的继承方式。
- ES6 的 class 继承
ES6 引入了 class(类),使得 JavaScript 的面向对象编程变得更加方便和直观。
javascript
class Parent {
constructor() {
this.name = 'parent';
}
sayHello() {
console.log('Hello from Parent');
}
}
class Child extends Parent {
constructor() {
super(); // 调用父类的 constructor
this.type = 'child';
}
}
let child = new Child();
console.log(child.name); // 'parent'
child.sayHello(); // 'Hello from Parent'
ES6 的 class 继承方式简洁明了,使得 JavaScript 的面向对象编程更加接近其他面向对象的语言。但是,请注意,ES6 的 class 实质上是基于原型链的语法糖,底层的实现仍然是原型链。