很多面向对象语言都支持两种继承:接口继承和实现继承。而ECMAScript只支持原型链实现。
原型链
基本思想:通过原型继承多个引用类型的属性和方法。
function SuperType() {
this.property = true;
}
SuperType.prototype.getSuperValue = function() {
return this.property;
};
function SubType() {
this.subproperty = false;
}
// 继承 SuperType
SubType.prototype = new SuperType();
SubType.prototype.getSubValue = function () {
return this.subproperty;
};
let instance = new SubType();
console.log(instance.getSuperValue()); // true
盗用构造函数
基本思路:在子类构造函数中调用父类构造函数。
apply():
var person = {
fullName: function() {
console.log(this.firstName + " " + this.lastName);
}
}
var person1 = {
firstName: "Bill",
lastName: "Gates",
}
person.fullName.apply(person1); // Bill Gates
call():
var person = {
fullName: function(city, country) {
console.log(this.firstName + " " + this.lastName + "," + city + "," + country);
}
}
var person1 = {
firstName:"John",
lastName: "Doe"
}
person.fullName.call(person1, "Oslo", "Norway"); // John Doe,Oslo,Norway
组合继承
基本思路:使用原型链继承原型上的属性和方法,而通过盗用构造函数继承实例属性。
function SuperType(name){
this.name = name;
this.colors = ["red", "blue", "green"];
}
SuperType.prototype.sayName = function() {
console.log(this.name);
};
function SubType(name, age){
// 继承属性
SuperType.call(this, name);
this.age = age;
}
// 继承方法
SubType.prototype = new SuperType();
SubType.prototype.sayAge = function() {
console.log(this.age);
};
let instance1 = new SubType("Nicholas", 29);
instance1.colors.push("black");
console.log(instance1.colors); // "red,blue,green,black"
instance1.sayName(); // "Nicholas";
instance1.sayAge(); // 29
let instance2 = new SubType("Greg", 27);
console.log(instance2.colors); // "red,blue,green"
instance2.sayName(); // "Greg";
instance2.sayAge(); // 27
原型式继承
基本思路:即使不自定义类型也可以通过原型实现对象之间的信息共享
Object.create():
let person = {
name: "Nicholas",
friends: ["Shelby", "Court", "Van"]
};
let anotherPerson = Object.create(person, {
name: {
value: "Greg"
}
});
console.log(anotherPerson.name); // "Greg"
寄生式继承
基本思路:创建一个实现继承的函数,以某种方式增强对象,然后返回这个对象。
function createAnother(original){
let clone = object(original); // 通过调用函数创建一个新对象
clone.sayHi = function() { // 以某种方式增强这个对象
console.log("hi");
};
return clone; // 返回这个对象
}
let person = {
name: "Nicholas",
friends: ["Shelby", "Court", "Van"]
};
let anotherPerson = createAnother(person);
anotherPerson.sayHi(); // "hi"
寄生式组合继承
基本思路:不通过调用父类构造函数给子类原型赋值,而是取得父类原型的一个副本。
function SuperType(name) {
this.name = name;
this.colors = ["red", "blue", "green"];
}
SuperType.prototype.sayName = function() {
console.log(this.name);
};
function SubType(name, age) {
SuperType.call(this, name);
this.age = age;
}
function inheritPrototype(subType, superType) {
let prototype = object(superType.prototype); // 创建对象
prototype.constructor = subType; // 增强对象
subType.prototype = prototype; // 赋值对象
}
inheritPrototype(SubType, SuperType);
SubType.prototype.sayAge = function() {
console.log(this.age);
};