2011-07-07 62 views
24

比方说,我有以下代码片段。如何调用父构造函数?

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

testChild.prototype = new test(); 

function testChild(){} 

var instance = new testChild('hi'); 

是否有可能得到alert('hi')?我现在得到undefined

回答

6

这就是你在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输出相比,代码略有修改,并且评论为更易读。

+0

+1分析和jsFiddle示例 – JCotton

0

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

+0

//仍然无法正常工作.. – Moon

+0

//是的......我可以手动调用测试,但我想要做的就是拨测()不喜欢,我们可以在其他OOP语言调用它。 – Moon

3

通过利用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'); 
+0

这可能是跨浏览器最多的解决方案,它利用了定义良好的语言标准。 –

+0

另外请注意,这可能会被重写为'this .__ proto __。apply(this,arguments)',因此它更通用且可重用。另外请注意,如果使用'test.create'来定义继承,就像在'testChild.prototype = Object.create(test.prototype);'中一样,这似乎是一种在野外创建继承的公认方法。 –

98

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'); 
+1

谢谢,绝对是在JS中做到这一点的方式:P –

+0

你这样做会搞砸原型链。做到这一点的方式实际上更像http://js-bits.blogspot.com.au/2010/08/javascript-inheritance-done-right.html – papercowboy

+0

@cayuu这是如何搞乱了原型链? – roylaurie

14

您已经有很多答案,但我会在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 
+0

好点。不幸的是,即使IE11(http://kangax.github.io/compat-table/es6/)也不支持'super()',这可能是生产环境中的一个问题。 – BurninLeo

+0

好的提醒像往常一样,如果可能的话,将源代码转换为ES5是一个好主意,因为这和其他不兼容。你可以使用Webpack,Typescript等工具来做到这一点。 – Sk606