【问题标题】:how to call parent constructor?如何调用父构造函数?
【发布时间】:2011-09-30 20:38:06
【问题描述】:

假设我有以下代码 sn-p。

function test(id) { alert(id); }

testChild.prototype = new test();

function testChild(){}

var instance = new testChild('hi');

有没有可能得到alert('hi')?我现在收到undefined

【问题讨论】:

    标签: javascript inheritance


    【解决方案1】:

    JS OOP ...

    // parent class
    var Test = function(id) {
        console.log(id);
    };
    
    // child class
    var TestChild = function(id) {
        Test.call(this, id); // call parent constructor
    };
    
    // extend from parent class prototype
    TestChild.prototype = Object.create(Test.prototype); // keeps the proto clean
    TestChild.prototype.constructor = TestChild; // repair the inherited constructor
    
    // end-use
    var instance = new TestChild('foo');
    

    【讨论】:

    • 谢谢,绝对是在 JS 中执行此操作的方法:P
    • 这样做会弄乱原型链。这样做的方式其实更像js-bits.blogspot.com.au/2010/08/…
    • @cayuu 这怎么弄乱了原型链?
    • 道歉,“搞砸了”是苛刻的 - 它使 dirty 原型链,将所有父实例属性分配为原型属性(这可能不是您想要的),但是如果您不关心该技术,则该技术有效 - 例如:imgur.com/NBDA5ob(干净的继承会将“id”作为构造函数实例化的实例属性,而不是原型实体)。
    • @cayuu 我来看看你现在的意思。我已经切换到 Object.create() 因为它不使用实例化。 Object.create() 的第二个参数也很酷——它创建了真正的常量。
    【解决方案2】:

    你已经有很多答案了,但我会抛出 ES6 方式,恕我直言,这是执行此操作的新标准方式。

    class Parent { 
      constructor() { alert('hi'); } 
    }
    class Child extends Parent { 
      // Optionally include a constructor definition here. Leaving it 
      // out means the parent constructor is automatically invoked.
      constructor() {
        // imagine doing some custom stuff for this derived class
        super();  // explicitly call parent constructor.
      }
    }
    
    // Instantiate one:
    var foo = new Child();  // alert: hi
    

    【讨论】:

    • 好点。不幸的是,即使 IE11 (kangax.github.io/compat-table/es6) 也不支持 super(),这在生产环境中可能是一个问题。
    • 好提醒? 像往常一样,如果可能,最好将源代码转换为 ES5 以解决此问题和其他不兼容问题。你可以使用 Webpack、Typescript 等工具来做到这一点。
    【解决方案3】:

    这就是你在 CoffeeScript 中的做法:

    class Test
      constructor: (id) -> alert(id)
    
    class TestChild extends Test
    
    instance = new TestChild('hi')
    

    不,我不是要发动一场圣战。相反,我建议查看生成的 JavaScript 代码以了解如何实现子类化:

    // Function that does subclassing
    var __extends = function(child, parent) {
      for (var key in parent) {
        if (Object.prototype.hasOwnProperty.call(parent, key)) {
          child[key] = parent[key];
        }
      }
      function ctor() { this.constructor = child; }
      ctor.prototype = parent.prototype;
      child.prototype = new ctor;
      child.__super__ = parent.prototype;
      return child;
    };
    
    // Our code
    var Test, TestChild, instance;
    
    Test = function(id) { alert(id); };
    
    TestChild = function() {
      TestChild.__super__.constructor.apply(this, arguments);
    }; __extends(TestChild, Test);
    
    instance = new TestChild('hi');
    
    // And we get an alert
    

    http://jsfiddle.net/NGLMW/3/查看它的实际应用。

    为了保持正确,与 CoffeeScript 输出相比,对代码稍作修改并添加注释以使其更具可读性。

    【讨论】:

      【解决方案4】:

      通过利用variable argumentsapply() 方法,您可以这样做。这是此示例的fiddle

      function test(id) { alert(id); }
      function testChild() {
        testChild.prototype.apply(this, arguments);
        alert('also doing my own stuff');
      }
      testChild.prototype = test;
      var instance = new testChild('hi', 'unused', 'optional', 'args');
      

      【讨论】:

      • 这可能是利用定义明确的语言标准的最跨浏览器的解决方案。
      • 另请注意,这可能可以重写为this.__proto__.apply(this, arguments),因此它更通用且可重用。另请注意,如果您使用 Object.create 定义继承,就像在 testChild.prototype = Object.create(test.prototype); 中一样,这将不起作用,这似乎是在野外创建继承的一种相当接受的方式。
      【解决方案5】:

      您需要在设置原型之前声明function testChild()。然后你需要调用testChild.test 来调用该方法。我相信你想设置testChild.prototype.test = test,然后你可以调用testChild.test('hi'),它应该可以正确解决。

      【讨论】:

      • // 是的...我可以手动调用 test,但我想做的是调用 test() 而不像在其他 OOP 语言中那样调用它。
      猜你喜欢
      • 2010-12-06
      • 2021-07-17
      • 1970-01-01
      • 2018-01-31
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-09-28
      • 1970-01-01
      相关资源
      最近更新 更多