2011-07-07 186 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

相關問題