继承

借用构造函数,借助call或apply,使用Superclass构造函数,缺少函数复用
Superclass.call(this, name)这里使Subclass继承了Superclass的实例属性this.name,但无法使用Superclass原型链上的属性及方法test.say()会抛出一个test.try is not a function异常。

function applyOrCall() {
    function Superclass(name = 'default') {
        this.name = name;
    }
    Superclass.prototype.try = function () {
        console.log('ok');
    };

    function Subclass(age = 22, name) {
        this.age = age;
        Superclass.call(this, name);
        this.say = function () {
            console.log(`this.name=${this.name}...this.age=${this.age}`);
        };
    }

    const test = new Subclass(23);
    test.say();
    console.log(`test instanceof Subclass`, test instanceof Subclass);
    console.log(`test instanceof Superclass`, test instanceof Superclass);
    console.log(test.__proto__.constructor);
    console.log(Subclass.prototype.constructor);
}
applyOrCall();

原型链继承,使用prototype指向Superclass对象,子类无法给父类传递参数,无法使用字面量添加新方法,所有子类对象共享父类所有方法和属性(引用类型),Subclass.prototype = new Superclass()此时Subclass原型对象拥有Superclass实例,并且被所有Subclass实例共享。

function prototype() {
    function Superclass(name = 'default') {
        this.name   = name;
        this.colors = ['r', 'y'];
    }

    function Subclass(age = 22) {
        this.age = age;
        this.say = function () {
            console.log(`this.name=${this.name}...this.age=${this.age}`);
        };
    }

    Subclass.prototype             = new Superclass();
    Subclass.prototype.constructor = Subclass;

    const test  = new Subclass(23);
    const test1 = new Subclass(24);
    test.colors.push('b');
    console.log(test.colors);
    console.log(test1.colors);
    test.say();
    test1.say();
    console.log(`test instanceof Subclass`, test instanceof Subclass);
    console.log(`test instanceof Superclass`, test instanceof Superclass);
    console.log(test.__proto__.constructor);
    console.log(Subclass.prototype.constructor);
}
prototype();

组合继承,prototype+call/apply,借用构造函数对实例属性继承,prototype对共享方法继承,会调用两次父类构造函数,第一次Subclass.prototyp= new Superclass();此时Subclass原型对象为Superclass实例,并且被所有Subclass实例共享,当调用new Subclass()Superclass.call(name)第二次父类构造函数被调用,此时Superclass继承的实例属性覆盖原型链上继承的父类属性。

function prototypeApplyCall() {
function Superclass(name = 'default') {
this.name = name;
}

Superclass.prototype.say = function () {
    console.log(this.name);
};

function Subclass(age = 22, name) {
    this.age = age;
    Superclass.call(name);
}

Subclass.prototype             = new Superclass();
Subclass.prototype.constructor = Subclass;

const test = new Subclass(23);
test.say();
console.log(`test instanceof Subclass`, test instanceof Subclass);
console.log(`test instanceof Superclass`, test instanceof Superclass);
console.log(test.__proto__.constructor);
console.log(Subclass.prototype.constructor);

}
prototypeApplyCall();

ES6 Class继承,必须在子类`constructor`中最先调用`super()`方法

function Class() {
class Superclass {
constructor(name = 'default') {
this.name = name;
}
}
class Subclass extends Superclass {
constructor(age = 22, name) {
super(name);
this.age = age;
}

    say() {
        console.log(`this.name=${this.name}...this.age=${this.age}`);
    }
}

const test = new Subclass(23);
test.say();
console.log(`test instanceof Subclass`, test instanceof Subclass);
console.log(`test instanceof Superclass`, test instanceof Superclass);
console.log(test.__proto__.constructor);
console.log(Subclass.prototype.constructor);

}
Class();

Node util.inherits;`inherits` 的主要实现还是基于原型链

ctor.super_ = superclass;
Object.setPrototypeOf(subclass.prototype, superclass.prototype);

function inherits() {
function Superclass(name = 'default') {
this.name = name;
}

function Subclass(age = 22, name) {
    this.age = 22;
    Superclass.call(this, name);

    this.say = function () {
        console.log(`this.name=${this.name}...this.age=${this.age}`);
    };

}

require('util').inherits(Subclass, Superclass);

const test = new Subclass(23);
test.say();
console.log(`test instanceof Subclass`, test instanceof Subclass);
console.log(`test instanceof Superclass`, test instanceof Superclass);
console.log(test.__proto__.constructor);
console.log(Subclass.prototype.constructor);

}
inherits();

你可能感兴趣的:(继承)