JS-ES5模仿super与多级继续(三)

参考文章

  1. js多层继续 super要领

参考文章1中供应了一个思绪, _super不一定假如一个变量, 也可所以一个函数, 只需它能返回我们希冀的父级对象就能够了. 下面是我对它给出的源码的一些修正和解释, 别的有3个测试示例.

/*
 * @author: general
 * @github: https://gist.github.com/generals-space/a75cfca06e1f8d463022e0e02446c363
 */
/*
 * 要想具有_super()要领, 必需继续SuperExtend类.
 * 注重: 
 * 1. inherits要领中不要再在assign时为子类增加指向父类自身的属性了, 会出题目的.
 * 2. 当需要运用_super()要领挪用父类的某个要领时, 必需要保证子类有同名要领, 需要经由过程子类的要领挪用父类要领才行
 */
function SuperExtend(){}
SuperExtend.prototype._super = function(){
    // caller挪用者应当会是子类的成员要领对象, 或是子类组织函数自身
    var caller = arguments.callee.caller;
    // 这里先获得this所属的组织函数类
    var chain = this.constructor;
    var parent = null;
    // 沿继续链一向向上遍历, 最少要遍历到SuperExtend的第一个子类
    // 目的是**找到主调函数究竟属于继续链上的哪一层级, 然后才获得这个挪用者的父类, 也就是我们需要的super对象**
    while(chain && chain.prototype){
        // 对象的隐式原型`__proto__`属性是一个指针, 它指向**组织本对象的**, **组织函数类**, **的原型**.
        // 然则因为inherits的自定义继续机制, chain.__proto__指向的是父级组织函数类(chain自身为子级组织函数类)
        parent = chain.__proto__;
        // 假如挪用者正好是组织函数类自身, 申明是在组织函数类的函数体中挪用的,
        // 直接返回父级组织函数类自身
        if(caller == chain) return parent;

        // 假如挪用者不是子级组织函数类, 就应当是原型中的要领了.
        var props = Object.getOwnPropertyNames(chain.prototype);
        for(var i = 0; i < props.length; i ++){
            // 这里虽然相称, 但有多是当前类从上一层父类继续而来的属性, 而当前类自身并没有定义过这个要领.
            // 需要进一步确认, 即确认父类原型上没有与它完全相同的要领(固然, 要领名能够一样).
            if(caller == chain.prototype[props[i]] && caller != parent.prototype[props[i]]){
                return parent.prototype;
            }
        }
        chain = parent;
    }
    return chain;
};
/*
 * function: 自定义通用继续要领.
 * 运用要领: inherits(子类, 父类)
 */ 
function inherits(subClass, superClass){
    Object.assign(subClass.prototype, superClass.prototype, {
        constructor: subClass,
    });
    // 竖立这类联络后, 相当于subClass成了superClass的实例了
    // 基础等价于subClass.prototype = superClass
    Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; 
}

3个测试示例以下

测试用例1. 基础测试

// 测试用例1. 基础测试
function A(a){
    this.a = a;
}

inherits(A, SuperExtend);

A.prototype.sayHi = function(){
    console.log(this.a);
};

function B(a, b){
    this._super().call(this, a);
    this.b = b;
}

inherits(B, A);

B.prototype.sayHi = function(){
    this._super().sayHi.call(this);
    console.log(this.a, this.b);
};

function C(a, b, c){
    // 这里获得的是父级组织函数类自身, 直接call挪用即可
    this._super().call(this, a, b);
    this.c = c;
}

inherits(C, B);

C.prototype.sayHi = function(){
    // 这里获得的是父级组织函数类的原型对象
    this._super().sayHi.call(this);
    console.log(this.a, this.b, this.c);
};

var c = new C(2, 5, 8);
c.sayHi();

测试用例2. 考证同层级函数间挪用的状况

// 测试用例2. 考证同层级函数间挪用的状况
function A(a){
    this.a = a;
}

inherits(A, SuperExtend);

A.prototype.sayA = function(){
    this.sayB();
};

A.prototype.sayB = function(){
    console.log(this.a);
};

function B(a, b){
    this._super().call(this, a);
    this.b = b;
}

inherits(B, A);

B.prototype.sayB = function(){
    this._super().sayB.call(this);
    console.log(this.a, this.b);
};

function C(a, b, c){
    // 这里获得的是父级组织函数类自身, 直接call挪用即可
    this._super().call(this, a, b);
    this.c = c;
}

inherits(C, B);

var c = new C(2, 5, 8);
c.sayA();

测试用例3. 考证主调函数与被调函数不同名的状况

// 测试用例3. 考证主调函数与被调函数不同名的状况
function A(a){
    this.a = a;
}

inherits(A, SuperExtend);

A.prototype.sayA = function(){
    console.log(this.a);    
};

function B(a, b){
    this._super().call(this, a);
    this.b = b;
}

inherits(B, A);

B.prototype.sayB = function(){
    this._super().sayA.call(this);
    console.log(this.a, this.b);
};

function C(a, b, c){
    // 这里获得的是父级组织函数类自身, 直接call挪用即可
    this._super().call(this, a, b);
    this.c = c;
}

inherits(C, B);

var c = new C(2, 5, 8);
c.sayB();
    原文作者:general
    原文地址: https://segmentfault.com/a/1190000013021514
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞