原型链继承是 JavaScript 中最基本的继承方式,其核心思想是利用原型让一个引用类型继承另一个引用类型的属性和方法
。具体实现方式如下:
function Parent() {
this.name = 'parent';
}
Parent.prototype.sayName = function () {
console.log(this.name);
}
function Child() {}
Child.prototype = new Parent();
let child1 = new Child();
在上面的代码中,Child.prototype对象通过new Parent()语句继承了Parent.prototype对象的属性和方法,从而使Child函数的实例可以访问这些属性和方法
。但是,这种方式有一个缺点
,即所有的实例共享原型对象
,如果一个实例修改了原型对象,其他实例的属性和方法也会受到影响。
构造函数继承是指在子类构造函数内部调用父类构造函数
,从而实现对父类实例属性的继承
。具体实现方式如下:
function Parent(name) {
this.name = name;
}
function Child(name) {
Parent.call(this, name);
}
let child1 = new Child('child1');
在上面的代码中,Child构造函数通过Parent.call(this, name)
语句调用了Parent构造函数,从而实现对父类实例属性的继承。但是,这种方式无法继承父类原型对象上的属性和方法
。
组合继承是将原型链继承和构造函数继承结合起来的一种继承方式。具体实现方式如下:
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;
let child1 = new Child('child1');
在上面的代码中,Child构造函数通过Parent.call(this, name)
语句调用了Parent构造函数,从而实现对父类实例属性的继承。同时,Child.prototype对象通过new Parent()语句继承了Parent.prototype对象的属性和方法
,从而使Child函数的实例可以访问这些属性和方法。这种方式的优点是可以同时继承父类实例属性和父类原型对象上的属性和方法,
原型式继承是指通过使用一个已有的对象作为新对象的原型来创建新对象,从而实现继承。具体实现方式如下:
function createObject(obj) {
function F() {}
F.prototype = obj;
return new F();
}
let parent = {
name: 'parent',
sayName: function() {
console.log(this.name);
}
};
let child = createObject(parent);
在上面的代码中,createObject函数通过将一个空函数的原型设置为obj
,从而创建了一个新的对象,并将新对象的原型指向obj
,从而实现了继承。这种方式的缺点是所有新对象的实例属性都会共享obj对象的属性,导致无法实现真正意义上的继承。
寄生式继承是指通过创建一个实现继承的函数,然后在函数内部以某种方式增强对象,最后返回这个对象。具体实现方式如下:
function createObject(obj) {
let clone = Object.create(obj);
clone.sayName = function() {
console.log(this.name);
}
return clone;
}
let parent = {
name: 'parent'
};
let child = createObject(parent);
在上面的代码中,createObject函数创建了一个新对象,并将新对象的原型指向obj对象。然后,createObject函数通过增强新对象的方式,在新对象上添加了sayName方法,从而实现继承和增强。这种方式的缺点是会增加对象的复杂度和难以维护。
寄生组合式继承是指通过借用构造函数来继承实例属性,然后通过将原型设置为一个继承父类原型的实例来继承父类原型上的属性和方法。具体实现方式如下:
function inheritPrototype(subType, superType) {
let prototype = Object.create(superType.prototype);
prototype.constructor = subType;
subType.prototype = prototype;
}
function Parent(name) {
this.name = name;
}
Parent.prototype.sayName = function () {
console.log(this.name);
}
function Child(name) {
Parent.call(this, name);
}
inheritPrototype(Child, Parent);
let child1 = new Child('child1');
在上面的代码中,inheritPrototype函数创建了一个临时构造函数,并将临时构造函数的原型设置为superType的原型。然后,将子类的原型设置为临时构造函数的实例,从而实现了对父类原型的继承。这种方式的优点是可以同时继承父