ES5和ES6的类的继承

489 阅读2分钟

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