0

I have found and adapted a JavaScript "class" extend function from coffeescript:

var extend = (function() {

    var hasProp = Object.prototype.hasOwnProperty;

    function ctor(child) {
        this.constructor = child;
    }

    return function(child, parent) {
        for (var key in parent) {
            if (hasProp.call(parent, key)) {
                child[key] = parent[key];
            }
        }
        ctor.prototype = parent.prototype;
        child.prototype = new ctor(child);
        child.__super__ = parent.prototype;
        // child.prototype.__super__ = parent.prototype; // better?
        return child;
    };

})();

I am wondering, if there is a reason why they used child.__super__ instead of child.prototype.__super__ (see out-commented code line).

I like the out-commented version more because:

  1. You can access super properties via this.__super__.propertyName instead of ClassName.__super__.propertyName. So you have no redundancy in the class naming.

  2. This makes even more sense for nested inheritance since you can use this.__super__.__super__.propertyName instead of ClassName.__super__.constructor.__super__.propertyName

I do not see any reason for it, but you could even still call "static" functions in a "static" way like that:

ClassName.prototype.__super__.constructor.staticMethod()

Are there any drawbacks with my version that I might have overlooked?

EDIT: I corrected the line to var hasProp = Object.prototype.hasOwnProperty;

2
  • Where have you "found" this? Is it from the code that CoffeeScript generates? Commented Jul 11, 2014 at 14:08
  • Yes exactly, but I slightly changed it. Commented Jul 12, 2014 at 11:46

1 Answer 1

3

Because you're not supposed to use __super__ in your code at all.

It's a compiler artifact, every use of the super macro/keyword/whatever it is will compile to

ClassName.__super__.methodName.call(this, …) // or
ClassName.__super__.methodName.apply(this, …)
// or, in static class functions even
ClassName.__super___.constructor.functionName.call(this, …)

They don't trust the dynamic this binding that you have proposed to use (this.__super__), they rather went for a static reference of the parent. Actually it might have been a good idea not to use a property at all, but just a local super variable in their module scope.


Also, this.__super__ will not work in an inherited method:

function A() { }
A.prototype.method = function() { console.log("works") };

function B() { A.call(this); }
B.prototype = Object.create(A.prototype);
B.prototype.__super__ = A.prototype;
B.prototype.method = function() { this.__super__.method.call(this); }


function C() { B.call(this); }
C.prototype = Object.create(B.prototype);
C.prototype.__super__ = B.prototype;

var b = new B(), c = new C();
b.method() // "works"
c.method() // Maximum recursion depth exceeded

Stack Overflow because you did not get the .__super__ that you expected!

Sign up to request clarification or add additional context in comments.

1 Comment

Ok, I see I get the same error // Maximum recursion depth exceeded

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.