资讯专栏INFORMATION COLUMN

JS-ES5模拟super与多级继承(三)

VioletJack / 2110人阅读

摘要:参考文章多层继承方法参考文章中提供了一个思路不一定要是一个变量也可以是一个函数只要它能返回我们期望的父级对象就可以了下面是我对它给出的源码的一些修改和注释另外有个测试示例要想拥有方法必须继承类注意方法中不要再在时为子类添加指向父类本身的属

参考文章

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

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/92862.html

相关文章

  • JS-ES5模拟super多级继承(一)

    摘要:参考文章多层继承方法本系列文章对实现多级继承做一个学习和探究第三篇给出最终的模拟代码及测试用例简单的父子继承父类子类原型链继承这里我用了关键字表示了继承的父类方法可以将其附加到子类实例对象上用起来会方便一点但是比较致命的一点是这种方式不适 参考文章 js多层继承 super方法 本系列文章对js es5实现多级继承做一个学习和探究, 第三篇给出最终的模拟代码及测试用例. 简单的父-子继...

    李世赞 评论0 收藏0
  • JS-ES5模拟super多级继承(二)

    摘要:参考文章官网是一个的编译器它可以将的代码转换成等价的我们看看它是怎么模拟关键字的与上面等价的语句如下貌似不支持多重继承啊覆写子类的对象设置隐式原型感觉这样很怪因为这样意为着子类将成为父类的实例对象呃类似的概念但我不觉得父子类关系与类和实 参考文章 Babel官网 babel是一个es6->es5的编译器, 它可以将es6的代码转换成等价的es5. 我们看看它是怎么模拟super关键字的...

    yearsj 评论0 收藏0
  • javascript之模拟继承

    摘要:欢迎关注我的博客正文让我来构造函数其实,模拟一个类的方式非常的简单构造函数。我们先来看一个例子这里通过构造函数模拟出来的类,其实和其他语言的类行为上是基本一致的,唯一的区别就是它不具备私有方法。 前言 ES6时代的来临,使得类继承变得如此的圆滑。但是,你有思考过ES6的类继承模式吗?如何去实现它呢? 类继承对于JavaScript来说,实现方式与Java等类语言大不相同。熟悉JavaS...

    Jochen 评论0 收藏0
  • ES6—class面向对象编程(8)

    摘要:接下来我们看下类的写法,这个就很接近于传统面向对象语言了。如果你想了解传统面向对象语言,这里是一个好切入点。作为对象时,指向父类的原型对象。这些就是为将来在中支持面向对象的类机制而预留的。 在ES5中,我们经常使用方法或者对象去模拟类的使用,并基于原型实现继承,虽然可以实现功能,但是代码并不优雅,很多人还是倾向于用 class 来组织代码,很多类库、框架创造了自己的 API 来实现 c...

    wangjuntytl 评论0 收藏0
  • 超级白中白的学习进程(2):继承(Extends)

    摘要:父类中的访问权限一定要小于或者等于子类访问权限的个关键字访问权限大小,其中为默认值,不用写。下面是一个典型的代码父类代码子类代码测试类代码输出结果在子类那里已经表明。 继承(Extends)1、前言还是先说一下博主本人的一些基本情况吧。本人去年刚刚毕业,专业是电气工程及其自动化,就是在大学期间完全没有接触过JAVA,也就稍稍了解了一下C语言。后来找了现在的工作也是和编程没有任何关系,是...

    pkwenda 评论0 收藏0

发表评论

0条评论

VioletJack

|高级讲师

TA的文章

阅读更多
最新活动
阅读需要支付1元查看
<