ES5和ES6的類的繼承

GetFullStack發表於2018-04-08

ES3版類的繼承

function Parent(name) {
    this.name = name
}

function Child(name) {
    Parent.call(this, name)
}

function inherit(Child, Parent) {
    function Prototype() {} // 中間物件
    Prototype.prototype = Parent.prototype; // 將父類原型掛到中間物件的原型上
    var prototype = new Prototype();

    prototype.constructor = Child; // 將中間物件的建構函式指向子類
    Child.prototype = prototype; // 將中間物件掛到子類上
}

inherit(Child, Parent);
複製程式碼

ES5改進版類的繼承

function Parent(name) {
    this.name = name
}
Parent.staticFn = function() {
    console.log('ok')
}

function Child(name) {
    Parent.call(this, name)
}

function inherit(Child, Parent) {
    // 用Object.create來建立空白中間物件
    var prototype = Object.create(Parent.prototype, {
        constructor: {
            value: Child
        }
    });

    prototype.constructor = Child; // 將中間物件的建構函式指向子類
    Child.prototype = prototype; // 將中間物件掛到子類上
}

inherit(Child, Parent);
複製程式碼

PS:問題是靜態方法無法繼承,改進:

Child.__proto__ = Parent; //將父類指定到子類的__proty__上。

Child.staticFn() // ok
複製程式碼

ES6版類的繼承

class Parent {
    constructor(name) {
        this.name = name;
    }
    getName() {
        return this.name
    }
    // 通過類來呼叫的
    static fn() {
        return 100;
    }
}
// es6的extends方法可以繼承私有屬性還可以公有屬性
// 靜態方法只能類呼叫 而且可以繼承
class Child extends Parent {
    constructor(name, age) {
        super(name); // 子類有建構函式必須使用super //Parent.call(this,name)
        this.age = age;
    }
}
複製程式碼

ES6版類的繼承的babel降級ES5版

function defineProperties(targetObject, properties) {
    properties.forEach(element => {
        var property = {
            value: element.value,
            enumerable: true, // 可以遍歷
            writeable: true, // 可以寫入修改
            configurable: true, // 可以刪除
        }
        Object.defineProperty(targetObject, element.key, property);
    });
}

function _createClass(targetObject, protoProperty, staticProperty) {
    if (protoProperty) {
        defineProperties(targetObject.prototype, protoProperty)
    }
    if (staticProperty) {
        defineProperties(targetObject, staticProperty)
    }
}

// 類的呼叫檢測 檢查當前類  有沒有new出來的 防止直接Parent()這樣當函式用
function _classCallCheck(instance, constructor) {
    if (!(instance instanceof constructor)) {
        throw new Error('without new')
    }
}

function _inherits(subClass, superClass) {
    // 子類繼承父類的公有方法
    subClass.prototype = Object.create(superClass.prototype, {
        constructor: {
            value: subClass
        }
    })
    // 子類繼承父類靜態方法
    subClass.__proto__ = superClass;
}

var Parent = function () {
    function Parent() {
        _classCallCheck(this, Parent);
        this.name = 'papa';
    }
    // 第一個陣列表示的是公共方法的描述
    // 第二個陣列表示的是靜態方法的描述 
    _createClass(Parent, [{
        key: 'getName',
        value: function () {
            return this.name
        }
    }], [{
        key: 'fn',
        value: function () {
            return 100;
        }
    }]);
    return Parent;
}();

var Child = function (Parent) {
    _inherits(Child, Parent);

    function Child() {
        _classCallCheck(this.Child);
        let that = this;
        let obj = Object.getPrototypeOf(Child).call(this); // 拿到子類的原型,也就是Child.__proto__,繼承父類的私有方法。
        // 建構函式預設返回的是當前物件的引用,是一個object型別
        if (typeof obj === 'object') {
            that = obj;
        }
        return that; // 返回子類的引用
    }
}(Parent);


複製程式碼

相關文章