2012-04-06 20 views
2

當我開始使用Javascript時,我學會了當你通過外部事件處理程序(如計時器)引用對象中的函數時,難以依靠this.來引用對象 - 它會引用事件的範圍(在定時器的情況下,我認爲它是window?)。Javascript:是否利用本地參考自己可以接受的編碼習慣?

我看到正在使用的解決方案是爲自己創建一個私有/本地引用,並在回調邏輯中使用它。例如:

function MyObject() { 
    var myThis = this; 
    this.foo = true; 
    this.callback = function() { return myThis.foo; } 
    this.interval = 30; 
    setInterval(function() { myThis.callback(); }, myThis.interval); 
} 

是對這樣的情況下,這種標準的編碼實踐,如果沒有,什麼是最佳的替代,爲什麼(例如,什麼是上面的例子中的風險。)?

+0

兩個堅實的答案 - 謝謝你們:) – chopperdave 2012-04-06 01:32:32

回答

4

現代替代方案將是使用Function.prototype.bind() ...

setInterval(this.callback.bind(this), this.interval); 

.bind()方法返回的功能與結合到第一個參數的值this你提供(在這種情況下是封閉this值)

它避免了在嵌套函數的變量範圍內(如問題所示)引用所需的this值在封閉變量範圍的變量中,從而提供更簡潔的代碼。


你可以找到一個兼容性補丁,足以滿足大多數情況下at MDN爲老年人實現。


側面說明,中this在JavaScript中值的問題不是一個問題的範圍,而是調用上下文的問題。

3

簡答:這是一個公認的做法,據我所知沒有任何缺點。

長(ish)回答:您可以操縱Prototype方法來做到這一點,請參閱我不是的答案。

1

您可以在不使用臨時「this」的情況下執行此操作,也無需使用閉包使用綁定。

這不是應該是在實踐中做到這一點的好方法,而是說明閉包和綁定上下文是如何工作的。如果你能理解爲什麼這會起作用,那麼你應該能夠看到你如何編碼function.prototype.bind來做同樣的事情。

http://jsfiddle.net/WRJqF/

function MyObject() { 
    this.foo = true; 
    this.callback = function() { 
     // firebug 
     console.log(this.foo); 
    }; 
    this.interval = 30; 

    setTimeout((function (that) { 
     return function() { 
      that.callback(); 
     }; 
    }(this)), this.interval); 

} 

它使用了兩個JavaScript的概念,你會用這麼多。

1 - 自我執行功能。通過在括號中包裝一個函數,它立即運行,並且有效地用它的返回值內聯替換,例如,

(function add(x,y) { 
    return x+y; 
}(2,3)) 

變成6

在上面的例子中,我們使用了一個自我執行的函數,並通過this作爲參數。這將創建一個閉包,並且該參數的值(名爲that只是爲了讓您感到迷惑)與該功能永久關聯。

2-作爲第一類對象。由於您可以返回一個函數(或者通常像使用其他值一樣使用它們),因此您可以從自執行函數返回一個函數,該函數與創建它的堆棧框架中的值this綁定。因此,自執行功能,有效,

function() { 
    that.callback(); 
}; 

...但「說,」實際上是在「本」,這是有效的創建功能時!

明白了嗎?

+0

...除了你提到的第三個概念:P – chopperdave 2012-04-06 02:28:31

+0

我刪除了它..對不起。在這種情況下它並沒有意義。但是查找'call'和'apply'是因爲它們被用來爲任何事物分配一個任意的'this'上下文。非常有用和緊密相關的綁定。 – 2012-04-06 02:29:24

+0

儘管這樣做,OP的原始代碼還通過定義本地'myThis'變量並在匿名函數中引用它來利用閉包。我認爲你的答案最好的部分是使用'.call()'代替OP原來的'myThis.callback()',但是你刪除了那部分! :P – 2012-04-06 02:34:45