JavaScript继承模式粗探
在 JavaScript 中实现继承的方式有很多,本文将介绍五种不同的继承模式,并通过示例代码进行说明和比较。
1. 原型链继承
原型链继承是最常见的一种继承方式,其基本思想是通过将子类的原型设为父类的实例实现继承。
function Parent() {
this.name = 'parent';
this.say = function() {
console.log('Hello, I am ' + this.name);
}
}
Parent.prototype.show = function() {
console.log('show in parent');
}
function Child() {}
Child.prototype = new Parent(); // 子类的原型设为父类的实例
const child = new Child();
console.log(child.name); // parent
console.log(child.show()); // "show in parent"
console.log(child.say()); // "Hello, I am parent"
但是原型链继承有一个致命的缺陷,即父类的引用属性会被所有子类实例共享,容易导致修改一个子类实例的引用属性时,其他实例的引用属性也会跟着改变。
2. 借用构造函数继承
借用构造函数继承是通过调用父类的构造函数来实现继承。
function Parent(name) {
this.name = name;
this.say = function() {
console.log('Hello, I am ' + this.name);
}
}
function Child(name) {
Parent.call(this, name); // 在子类构造函数中调用父类构造函数
}
const child1 = new Child('child1');
const child2 = new Child('child2');
console.log(child1.say()); // "Hello, I am child1"
console.log(child2.say()); // "Hello, I am child2"
但是借用构造函数继承的缺点是无法继承父类原型上的方法和属性。
3. 组合继承
组合继承是将原型链继承和借用构造函数继承结合起来,既能继承父类构造函数中的属性,又能继承父类原型上的方法。
function Parent(name) {
this.name = name;
this.say = function() {
console.log('Hello, I am ' + this.name);
}
}
Parent.prototype.show = function() {
console.log('show in parent');
}
function Child(name) {
Parent.call(this, name);
}
Child.prototype = new Parent(); // 将子类的原型设为父类的实例
Child.prototype.constructor = Child; // 修正constructor
const child = new Child('child');
console.log(child.name); // child
console.log(child.show()); // "show in parent"
console.log(child.say()); // "Hello, I am child"
可以看到,组合继承综合了原型链继承和借用构造函数继承的优点,但是存在一个缺点就是在使用子类生成对象时,调用了两次父类构造函数,第一次是在将子类原型指向父类实例时,第二次是在子类构造函数中。
4. 原型式继承
原型式继承是基于某个对象创建一个副本作为新对象的原型,然后扩展新对象,从而实现继承。
const parent = {
name: 'parent',
say: function() {
console.log('Hello, I am ' + this.name);
}
}
const child = Object.create(parent); // 基于parent创建child的原型
child.name = 'child';
console.log(child.say()); // "Hello, I am child"
但是原型式继承也存在跟原型链继承相同的问题,即引用类型的属性会被所有实例共享。
5. 寄生式继承
寄生式继承是在原型式继承的基础上,将扩展对象的过程封装在函数中,返回新对象。
const parent = {
name: 'parent',
say: function() {
console.log('Hello, I am ' + this.name);
}
}
function createChild(obj, name) {
const child = Object.create(obj);
child.name = name;
return child;
}
const child = createChild(parent, 'child');
console.log(child.say()); // "Hello, I am child"
总结
前面介绍了五种 JavaScript 继承模式,每种继承方式都有其优缺点,可以根据具体场景选择不同的继承方式,实现对象的多态。
本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:JavaScript继承模式粗探 - Python技术站