2013-04-20 66 views
0

考慮下面的例子原型的JavaScript構造

問題

bar,我可以怎樣獲得fooInstance變量? Foo的子女是否有辦法將其父母識別爲fooInstance?例如,我如何在bar中創建一個功能,返回fooInstance。需要注意的一點是,該條必須使用prototype命令創建,並且不能簡單地嵌套在Foo中,以便以此方式訪問任何Foo實例。

我的想法和爲什麼他們不工作

這將有可能重寫的功能,像這樣

var Foo = function(){ 
    this.identity = 'Foo'; 
}; 
Foo.prototype.createBar = function(){ 
    var parent = this; 
    function bar(){ 
     this.parent = parent; 
     this.identity = 'bar'; 
    }; 
    return new bar(); 
}; 
var fooInstance = new Foo(), 
    bar = fooInstance.createBar(); 

然而,對於創建易於閱讀的代碼,我寧願不使用的目的這種方法如果不需要的話。

進一步明確

讓我把這個問題的背景。我在CanvasRenderingContext2D上進行原型設計,以便canvas元素的所有上下文都將包含我的新方法。讓我們調用該方法foo並假定上下文是創建的畫布上下文。如何像這樣創建一個變量「new context.foo()」,使得foo函數可以使用上下文變量?

+1

什麼是'fooInstance'?什麼是「Foo」的「孩子」和「父母」?什麼是你調用但不定義的'bar'方法? 「原型指令」是什麼意思? – Bergi 2013-04-20 19:28:24

+0

順便說一句,[這個答案](http://stackoverflow.com/questions/13418669/javascript-do-i-need-to-put-this-var-for-every-variable-in-an-object/13418980# 13418980)可能會幫助您瞭解變量和屬性之間的差異。 – Bergi 2013-04-20 19:31:16

+0

讓我把問題放在背景下。我在CanvasRenderingContext2D上進行原型設計,以便canvas元素的所有上下文都將包含我的新方法。讓我們調用該方法foo並假定上下文是創建的畫布上下文。如何像這樣創建一個變量「new context.foo()」,使得foo函數可以使用上下文變量? – 2013-04-20 19:36:46

回答

1

我怎麼能創造酒吧函數將返回fooInstance

如果該功能被稱爲構造(與new),你不能真正做到這一點。在構造函數調用中,this keyword對「父」(您調用該方法的對象)的唯一引用被設置爲新實例。你只能通過閉包獲得引用,例如通過在父類的構造函數中創建構造函數(不適用於你)或通過從原型中的閉包返回構造函數(在第二個例子):

Foo.prototype.getBarCoonstructor = function() { 
    var parentFoo = this; 
    return function Bar() { 
     // constructor things 
     // using "parentFoo" reference 
    }; 
}; 
// Usage: 
var bar = new (foo.getBarConstructor())(); // ugly. 

而是爲getBarConstructor每個調用創建新的構造函數,你最好應該把它的方法之外,並把parentFoo作爲參數傳遞給它。你的想法已經相當好了。

function Bar(parent) { 
    // constructor things, referring "parent" 
} 
Bar.prototype.… = …; 

Foo.prototype.createBar = function() { 
    return new Bar(this); // passing the Foo instance 
}; 

(@plalx具有相同的解決方案,但包裹在一個模塊閉合)

+0

謝謝,我想問題是「this」是函數之間唯一的向上關係,並且使用構造函數可以有效地除去它。這是javascript阻礙我的那些時刻之一。 – 2013-04-20 19:53:19

0

Foo.prototype.bar只是一個關於Foo原型的函數。除非您在其範圍鏈中明確定義它,否則沒有辦法讓該函數知道其「父」。

I.e.如果你願意

var Foo = function(){ 
    this.identity = 'Foo'; 
}; 
var fooInstance = new Foo(); 

Foo.prototype.bar = function(){ 
    console.log(fooInstance); // retrieve from scope 
    this.identity = 'bar'; 
}; 
bar = new foo.bar(); 

這將工作。

+0

是的,但是一旦我創建了多個fooInstance該方法就會中斷。代碼需要是動態的。每個fooInstance都是唯一的,每個bar實例必須能夠獲得它的唯一父對象。 – 2013-04-20 19:38:51

2

如果您需要從bar對象引用fooInstance對象,你可以使用依賴注入是這樣的:

Foo.prototype.bar = function(fooInstance) { 
    this.identity = 'bar'; 
    this.fooInstance = fooInstance; 
}; 

var fooInstance = new Foo(), 
    bar = new foo.bar(fooInstance); 

你可以通過Foo實現工廠函數簡化創建過程。

Foo.prototype.createBar = (function() { 
    function Bar(parent){ 
     this.parent = parent; 
     this.identity = 'bar'; 
    }; 

    return function() { 
     return new Bar(this); 
    }; 
})(); 

var fooInstance = new Foo(), 
    bar = fooInstance.createBar(); 
+0

這正是我的想法,但我正在設計一個API,並發現這個繁瑣的用戶。然而,儘管工廠方法消除了傳遞參數的煩人需求,但在我的程序中,使用新的前綴在邏輯上更合理,我寧願讓用戶保持邏輯。子方法是否可以動態獲取原始對象?通常綁定和使用這可以完成這一點,但由於構造函數的性質,不適用於此...是否有任何其他方式? – 2013-04-20 19:47:00