【问题标题】:JavaScript inheritance and super constructorJavaScript 继承和超级构造函数
【发布时间】:2014-09-02 04:05:15
【问题描述】:

我从 coffeescript 中找到并改编了一个 JavaScript“类”扩展函数:

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

})();

我想知道,他们使用 child.__super__ 而不是 child.prototype.__super__ 是否有原因(请参阅注释掉的代码行)。

我更喜欢注释掉的版本,因为:

  1. 您可以通过this.__super__.propertyName 而不是ClassName.__super__.propertyName 访问超级属性。所以你在类命名上没有冗余。

  2. 这对于嵌套继承更有意义,因为您可以使用this.__super__.__super__.propertyName 而不是ClassName.__super__.constructor.__super__.propertyName

我看不出有什么原因,但您甚至可以像这样以“静态”方式调用“静态”函数:

ClassName.prototype.__super__.constructor.staticMethod()

我的版本是否有我可能忽略的缺点?

编辑:我将行更正为var hasProp = Object.prototype.hasOwnProperty;

【问题讨论】:

  • 你在哪里“找到”了这个?是来自 CoffeeScript 生成的代码吗?
  • 没错,但我稍微改了一下。

标签: javascript inheritance coffeescript


【解决方案1】:

因为您根本不应该在代码中使用__super__

这是一个编译器,每次使用super macro/keyword/whatever it is都会编译成

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

他们不信任您建议使用的dynamic this binding (this.__super__),而是选择了父级的静态引用。实际上,完全不使用属性可能是个好主意,而只是在其模块范围内使用本地 super 变量。


另外,this.__super__ 不能在继承的方法中工作:

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

堆栈溢出,因为您没有得到预期的.__super__

【讨论】:

  • 好的,我看到我得到了同样的错误 // 超出最大递归深度
猜你喜欢
  • 1970-01-01
  • 2017-04-05
  • 2021-11-15
  • 1970-01-01
  • 2012-01-31
  • 2013-09-17
  • 1970-01-01
  • 1970-01-01
  • 2012-10-16
相关资源
最近更新 更多