JavaScript 中实现继承有多种方式,这里介绍几种常见的方法:
1. 原型链继承
这是最基础的继承方式,通过将子类的原型设置为父类的一个实例来实现。
Javascript
深色版本
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;
};
var instance = new SubType();
console.log(instance.getSuperValue()); // true
2. 构造函数继承
使用父类的构造函数来增强子类的实例,通常用于传递参数给父类的构造函数。
Javascript
深色版本
function SuperType(name) {
this.name = name;
this.colors = ["red", "blue", "green"];
}
function SubType(name, age) {
// 继承了 SuperType,并且可以向 SuperType 传参
SuperType.call(this, name);
this.age = age;
}
var instance1 = new SubType("Nicholas", 29);
instance1.colors.push("black");
console.log(instance1.colors); // ["red", "blue", "green", "black"]
var instance2 = new SubType("Greg", 27);
console.log(instance2.colors); // ["red", "blue", "green"]
3. 组合继承
结合原型链继承和构造函数继承的优点,避免了它们各自的缺点。
Javascript
深色版本
function SuperType(name) {
this.name = name;
this.colors = ["red", "blue", "green"];
}
SuperType.prototype.sayName = function() {
console.log(this.name);
};
function SubType(name, age) {
// 第二次调用 SuperType()
SuperType.call(this, name);
this.age = age;
}
// 继承了 SuperType
SubType.prototype = new SuperType();
// 设置 constructor 指针指向正确的构造函数
SubType.prototype.constructor = SubType;
SubType.prototype.sayAge = function() {
console.log(this.age);
};
var instance1 = new SubType("Nicholas", 29);
instance1.colors.push("black");
console.log(instance1.colors); // ["red", "blue", "green", "black"]
instance1.sayName(); // Nicholas
instance1.sayAge(); // 29
var instance2 = new SubType("Greg", 27);
console.log(instance2.colors); // ["red", "blue", "green"]
instance2.sayName(); // Greg
instance2.sayAge(); // 27
4. 原型式继承
可以用来基于一个对象创建另一个对象,而不需要定义构造函数。
Javascript
深色版本
function object(o) {
function F() {}
F.prototype = o;
return new F();
}
var person = {
name: "Nicholas",
friends: ["Shelby", "Court", "Van"]
};
var anotherPerson = object(person);
anotherPerson.name = "Greg";
anotherPerson.friends.push("Rob");
var yetAnotherPerson = object(person);
yetAnotherPerson.name = "Linda";
yetAnotherPerson.friends.push("Barry");
console.log(person.friends); // ["Shelby", "Court", "Van", "Rob", "Barry"]
5. 寄生式继承
创建一个仅用于封装继承过程的函数,该函数在内部以某种方式增强对象,最后返回新的对象。
Javascript
深色版本
function createAnother(original) {
var clone = object(original); // 通过调用函数创建一个新对象
clone.sayHi = function() { // 以某种方式增强这个对象
console.log("hi");
};
return clone; // 返回这个对象
}
var person = {
name: "Nicholas",
friends: ["Shelby", "Court", "Van"]
};
var anotherPerson = createAnother(person);
anotherPerson.sayHi(); // "hi"
6. 寄生组合式继承
这是最常用的继承模式,通过借用构造函数来继承属性,通过原型链的混成形式来继承方法。这种方式既高效又灵活。
Javascript
深色版本
function inheritPrototype(subType, superType) {
var prototype = object(superType.prototype); // 创建对象
prototype.constructor = subType; // 增强对象
subType.prototype = prototype; // 指定对象
}
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;
}
inheritPrototype(SubType, SuperType); // 继承方法
SubType.prototype.sayAge = function() {
console.log(this.age);
};
var instance1 = new SubType("Nicholas", 29);
instance1.colors.push("black");
console.log(instance1.colors); // ["red", "blue", "green", "black"]
instance1.sayName(); // Nicholas
instance1.sayAge(); // 29
var instance2 = new SubType("Greg", 27);
console.log(instance2.colors); // ["red", "blue", "green"]
instance2.sayName(); // Greg
instance2.sayAge(); // 27