【问题标题】:Inheritance: Constructor doesn't run "super"?继承:构造函数不运行“超级”?
【发布时间】:2012-01-31 12:14:35
【问题描述】:

我在使用 JS 几个月后遇到了这种行为。由于我的Java背景,我很困惑:我创建了一个类并制作了子类。 调用子类的构造函数不会调用父构造函数。好的,我读到了这种行为,看起来很正常,对吧?

请参阅此 jsfiddle example 以帮助我澄清。

为了让我的子类构造函数运行它的每个父构造函数,我添加了以下内容(参见 jsfiddle example

好的,这样似乎效果更好。 现在,我想知道以下内容;有没有办法在不触发其构造函数的情况下指定超类? 比如下面运行 Node() 方法:

GameObject.prototype = new Node();
GameObject.prototype.constructor=GameObject;

(请参阅更新的 jsfiddle example

我不禁觉得我做得不对。由于我的真实模型跨 7 个子类分层,因此对我的构造函数总共有 21 次调用(6 + 5 + 4 + 3 + 2 + 1 = 21)。

我做错了吗?感谢您的宝贵时间!

【问题讨论】:

    标签: javascript inheritance constructor prototype chaining


    【解决方案1】:

    我的理解是,JavaScript 不会像 C++、Java 和 C# 等传统语言那样天真地实现类。我认为你可以通过使用一个 JavaScript 框架来获得你想要的行为,该框架将你在 Java 等语言中习惯的行为强加给你。

    Moo Tools 就是这样一种框架:http://mootools.net

    【讨论】:

      【解决方案2】:

      您本身并没有做错任何事。这是给定您的代码的预期行为。但是,您可以使用类似于"Simple JavaScript Inheritence" by John Resig 中描述的方法。可以找到关于类似方法的另一个讨论here on stackoverflow

      【讨论】:

      • 调用父级的构造函数设置继承错误
      【解决方案3】:

      一般来说,你做对了。但是您的构造函数会在其实例上创建属性,并且这些属性会分配给继承构造函数的原型。

      Subclass.prototype.animations,例如在原型上,由Subclass 的所有其他实例共享。从您的代码看来,您似乎打算为每个实例重新创建这些 animations

      如何解决这个问题?根本不要使用构造函数。使用对象字面量和Object.create

      var Node = {
          init: function () { this.animations = []; },
          doSomething: function () { console.log(this.animations); }
      };
      
      var GameObject = Object.create(Node);
      GameObject.doSomethingElse = function () { this.init(); this.doSomething(); }
      

      以继承的方式实例化

      var gameObj = Object.create(GameObject);
      gameObj.doSomethingElse();
      

      应该不会比这更难。

      Combining inheritance with the module pattern

      【讨论】:

      • 嘿,听起来不错,我喜欢有一个单独的“init”方法的想法。谢谢!
      • 所以...不要使用构造函数?这不是解决问题的好方法。正确的方法是使用不同的技术,它不涉及调用父级的构造函数来设置继承js-bits.blogspot.com/2010/08/…
      • 另外,this.animations 没有设置在原型上,它是在对象本身上完成的,写入总是在对象上,从不在原型上(除非你这样做 Constructor.prototype.animations = []),最后,建议使用[] 是可以的,但更好的建议是使用{},因为OP 没有将它用作数组,但它实际上是一张地图
      • @JuanMendes,animations 成为Redhead 原型的属性,而他却是Redhead.prototype = new GameObject();。我将编辑我的答案以表达我对(没有)构造函数的看法。
      • @Katspaugh 我明白了,它在原型上,因为它调用构造函数来设置继承,而父实例是附加到原型的。对不起,我应该意识到...
      【解决方案4】:

      您不需要调用父级的构造函数来设置继承链。见http://js-bits.blogspot.com/2010/08/javascript-inheritance-done-right.html

      以下是不好的,运行父级的构造函数只是为了设置原型链

      GameObject.prototype = new Node();
      GameObject.prototype.constructor = GameObject;
      

      更好的方法是使用附加原型而不实例化“超类”的代理构造函数。

      // Surrogate constructor
      var TempCtor = function(){};
      TempCtor.prototype = Node.prototype;
      // Setup the prototype chain without side effects
      GameObject.prototype = new tempCtor();
      GameObject.prototype.constructor=GameObject;
      

      而且你需要确保从子类调用父构造函数

      function GameObject() {
          // Call the parent's constructor
          Node.call(this);
      }
      

      我已经用一个示例更新了您的 jsfiddle,该示例显示了设置继承的正确方法http://jsfiddle.net/2caTD/5/

      【讨论】:

        猜你喜欢
        • 2014-09-02
        • 1970-01-01
        • 2017-04-05
        • 2021-11-15
        • 2018-04-21
        • 1970-01-01
        • 2012-10-16
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多