📅  最后修改于: 2023-12-03 15:11:41.750000             🧑  作者: Mango
继承是面向对象编程的一个重要概念。在JavaScript中,继承的实现方式与传统面向对象编程语言略有不同。本文将介绍如何在JavaScript中进行继承,包括原型链、构造函数绑定和组合继承三种实现方式。
在JavaScript中,每个对象都有一个原型对象。原型对象具有一个指向另一个原型对象的指针,构成了一个原型链。
对象可以通过该原型链来继承另一个对象的属性和方法。假设我们有一个父类
function Parent() {
this.name = 'parent';
}
Parent.prototype.sayName = function() {
console.log(this.name);
}
我们可以使用new
操作符创建一个子类实例,并将原型链指向父类的原型对象:
function Child() {}
Child.prototype = new Parent();
var child = new Child();
child.sayName(); // parent
这里我们将Child
的原型对象指向了一个新创建的Parent
实例,那么Child
实例就可以通过原型链继承Parent
的属性和方法。
值得注意的是,通过原型链实现继承时,如果在子类实例中修改属性和方法,其实是在子类实例中添加了一个同名属性或方法,而不是修改父类中的属性或方法。这会影响到所有子类实例和当前实例原型链上的对象。
child.name = 'child';
child.sayName(); // child
var child2 = new Child();
child2.sayName(); // parent
我们可以看到,修改了child
实例的name
后,虽然依然继承自父类,但是输出的name
已经不是从父类继承而来了。
通过原型链实现继承有一个致命缺陷:所有子类实例都会共享父类属性和方法。这是由于原型对象是共享的。
function Parent() {
this.colors = ['red', 'green', 'blue'];
}
function Child() {}
Child.prototype = new Parent();
var child1 = new Child();
child1.colors.push('purple');
var child2 = new Child();
console.log(child2.colors); // ['red', 'green', 'blue', 'purple']
我们在Child
的实例化对象中修改了共享的数组,导致其它实例也会因此受影响。
为了解决这个问题,我们可以通过构造函数绑定实现继承。这种方式会在子类实例内部创建一个新的父类实例,而不是将父类的原型对象赋值给子类原型对象。
function Parent() {
this.colors = ['red', 'green', 'blue'];
}
function Child() {
Parent.call(this);
}
var child1 = new Child();
child1.colors.push('purple');
var child2 = new Child();
console.log(child2.colors); // ['red', 'green', 'blue']
在子类构造函数中使用call
或apply
方法,可以将父类的属性绑定在子类的实例上,实现继承。
上述两种方式各有优缺点,组合继承是将它们合并在一起的最佳方式。
组合继承首先通过构造函数绑定创建子类实例的属性,在子类原型对象上通过原型链继承父类的方法。
function Parent(name) {
this.name = name;
this.colors = ['red', 'green', 'blue'];
}
Parent.prototype.sayName = function() {
console.log(this.name);
}
function Child(name) {
Parent.call(this, name);
}
Child.prototype = new Parent();
Child.prototype.constructor = Child;
var child1 = new Child('child1');
child1.sayName(); // child1
child1.colors.push('purple');
var child2 = new Child('child2');
console.log(child2.colors); // ['red', 'green', 'blue']
在这种方式下,每个子类实例都拥有父类实例的所有属性和方法,而且各自拥有独立的属性和方法。
JavaScript中的继承通过原型链、构造函数绑定和组合继承等方式实现。掌握这些继承方式可以有效地提高代码的复用性和可维护性。