Es5继承

发布时间 2023-04-25 15:00:50作者: 梭不梭看你

1、通过原型链继承:

缺点如下:
* 《1》原型中包含的引用值会在所有实例之间共享,修改一个实例,另一个实例会跟着修改
* 即:通过将属性定义在构造函数中
* 《2》子类实例化时,无法给父类构造函数传参

// 父类
function SuperType() {
    this.colors = ['red', 'blue', 'green']
}
// 子类
function SubType() { }
SubType.prototype = new SuperType()

let instance1 = new SubType()
instance1.colors.push('black')
console.log(instance1.colors)  // "red,blue,green,black"

let instance2 = new SubType()
console.log(instance2.colors)  // "red,blue,green,black"

2、借用构造函数继承

缺点如下:
* 《1》必须在构造函数中定义方法,因此函数不能复用
* 《2》子类不能访问父类原型上定义的方法
* 为确保 SuperType 构造函数不会覆盖 SubType 定义的属性,
* 可以在调用父类构造函数之后再给子类实例添加额外的属性

// 父类
function SuperType(name) {
    this.name = name
}
// 子类
function SubType(name1) {
    SuperType.call(this, name1)
    this.age = 28
}
let instance1 = new SubType('测试名称')
console.log(instance1.name) // 测试名称
console.log(instance1.age) // 28

3、组合式继承

* 缺点如下:
* 《1》组合式继承存在效率问题,父类构造函数会被调用两次,
* 第一次是在创建子类原型、第二次是在子类构造函数中调用
* 最终导致子类原型包含父类所有的实例属性

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); // 第二次调用 SuperType()
    this.age = age;
}
SubType.prototype = new SuperType(); // 第一次调用 SuperType()
SubType.prototype.constructor = SubType;
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

4、原型式继承

缺点如下:
* 《1》属性中包含的引用数值,会在对象之间共享
* 注:ECMAScript 5 通过增加 Object.create()方法将原型式继承的概念规范化了。这个方法接收两个
* 参数:作为新对象原型的对象,以及给新对象定义额外属性的对象(第二个可选)
* Object.create()的第二个参数与 Object.defineProperties()的第二个参数一样

function object(o) {
    function F() { }
    F.prototype = o
    return new F()
}

let person = {
    name: "Nicholas",
    friends: ["Shelby", "Court", "Van"]
};
let anotherPerson = object(person);
anotherPerson.name = "Greg";
anotherPerson.friends.push("Rob");
let yetAnotherPerson = object(person);
yetAnotherPerson.name = "Linda";
yetAnotherPerson.friends.push("Barbie");
console.log(person.friends); // "Shelby,Court,Van,Rob,Barbie"

5、寄生式继承

* 缺点如下:
* 《1》给对象添加函数会导致函数难以重用,与构造函数模式类似。

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"

6.寄生式组合继承  <完美解决方案  ES7class类的采用方案>

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);
};