1. 原型链继承
JavaScript中,每个函数都有一个prototype
属性,这个属性是一个指向原型对象的指针。原型对象默认包含一个名为constructor
的属性,指向原函数。当我们使用构造函数创建实例时,每个实例内部都有一个指向其构造函数原型对象的指针__proto__
(在ES6中,通过Object.getPrototypeOf()
方法访问)。如果原型对象中包含一个指向另一个类型的原型对象的指针,相应地,就形成了一个原型链。
function Parent() {
this.name = 'parent';
}
Parent.prototype.sayName = function() {
console.log(this.name);
};
function Child() {
this.age = 10;
}
// Child继承Parent
Child.prototype = new Parent();
Child.prototype.constructor = Child;
var child = new Child();
child.sayName(); // 'parent'
2. 借用构造函数继承(伪造对象或经典继承)
在子类的构造函数中,通过调用父类的构造函数,并使用call()
或apply()
方法,可以将父类的属性"借用"给子类实例。
function Parent(name) {
this.name = name;
}
function Child(name, age) {
Parent.call(this, name); // 继承Parent的name属性
this.age = age;
}
var child = new Child('child', 5);
console.log(child.name); // 'child'
3. 组合继承(原型链+借用构造函数继承)
组合继承是原型链继承和借用构造函数继承的组合,它结合了两种继承方式的优点,既可以通过原型链继承父类原型上的属性和方法,又可以通过构造函数继承父类的实例属性。
function Parent(name) {
this.name = name;
}
Parent.prototype.sayName = function() {
console.log(this.name);
};
function Child(name, age) {
Parent.call(this, name); // 继承属性
this.age = age;
}
Child.prototype = new Parent(); // 继承方法
Child.prototype.constructor = Child;
Child.prototype.sayAge = function() {
console.log(this.age);
};
var child = new Child('child', 5);
child.sayName(); // 'child'
child.sayAge(); // 5
4. 原型式继承
原型式继承是借助原型可以基于已有的对象创建新对象,同时实现原型链继承。
function object(o) {
function F() {}
F.prototype = o;
return new F();
}
var person = {
name: 'John',
friends: ['Sheldon', 'Leonard', 'Howard']
};
var anotherPerson = object(person);
anotherPerson.name = 'Jane';
anotherPerson.friends.push('Penny');
console.log(person.friends); // ['Sheldon', 'Leonard', 'Howard', 'Penny']
5. 寄生式继承
寄生式继承是创建一个仅用于封装继承过程的函数,该函数在内部以某种方式来增强对象,最后返回对象。
function createAnother(original) {
var clone = object(original); // 通过原型式继承获得原始对象的浅拷贝
clone.sayHi = function() { // 增强对象
console.log('hi');
};
return clone; // 返回增强后的对象
}
var person = {
name: 'John'
};
var anotherPerson = createAnother(person);
anotherPerson.sayHi(); // 'hi'