JS继承

60 阅读2分钟

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