Emulate super in javascript

后端 未结 11 1145
生来不讨喜
生来不讨喜 2020-12-08 10:18

Basically is there a good elegant mechanism to emulate super with syntax that is as simple as one of the following

  • this.$super.prop()
11条回答
  •  情书的邮戳
    2020-12-08 10:50

    The main difficulty with super is that you need to find what I call here: the object that contains the method that makes the super reference. That is absolutely necessary to get the semantics right. Obviously, having the prototype of here is just as good, but that doesn’t make much of a difference. The following is a static solution:

    // Simulated static super references (as proposed by Allen Wirfs-Brock)
    // http://wiki.ecmascript.org/doku.php?id=harmony:object_initialiser_super
    
    //------------------ Library
    
    function addSuperReferencesTo(obj) {
        Object.getOwnPropertyNames(obj).forEach(function(key) {
            var value = obj[key];
            if (typeof value === "function" && value.name === "me") {
                value.super = Object.getPrototypeOf(obj);
            }
        });
    }
    
    function copyOwnFrom(target, source) {
        Object.getOwnPropertyNames(source).forEach(function(propName) {
            Object.defineProperty(target, propName,
                Object.getOwnPropertyDescriptor(source, propName));
        });
        return target;
    };
    
    function extends(subC, superC) {
        var subProto = Object.create(superC.prototype);
        // At the very least, we keep the "constructor" property
        // At most, we preserve additions that have already been made
        copyOwnFrom(subProto, subC.prototype);
        addSuperReferencesTo(subProto);
        subC.prototype = subProto;
    };
    
    //------------------ Example
    
    function A(name) {
        this.name = name;
    }
    A.prototype.method = function () {
        return "A:"+this.name;
    }
    
    function B(name) {
        A.call(this, name);
    }
    // A named function expression allows a function to refer to itself
    B.prototype.method = function me() {
        return "B"+me.super.method.call(this);
    }
    extends(B, A);
    
    var b = new B("hello");
    console.log(b.method()); // BA:hello
    

提交回复
热议问题