2011-11-11 129 views
17

在存儲在對象原型中的事件處理程序中保留this JavaScript引用的正確方法是什麼?我想遠離創建像'_this'或'that'這樣的臨時變量,我不能使用像jQuery這樣的框架。我看到很多人談論使用「綁定」功能,但不確定如何在我的情況下實現它。在JavaScript原型事件處理程序中保留'this'引用

var Example = function(foo,bar){ 
    this.foo = foo; 
    this.bar = bar; 
}; 
Example.prototype.SetEvent = function(){ 
    this.bar.onclick = this.ClickEvent; 
}; 
Example.prototype.ClickEvent = function(){ 
    console.log(this.foo); // logs undefined because 'this' is really 'this.bar' 
}; 

回答

20

我覺得bind()是最乾淨的解決方案迄今:

this.bar.onclick = this.ClickEvent.bind(this); 

BTW的其他this被稱爲按照慣例that非常頻繁。

+3

我*討厭*創建一個引用這個叫做「那個」(a Crockford)。我更喜歡「實例」(la Stefanov)或「我」(一個ExtJS) –

+4

實際上,我討厭創建'this'引用,不管它們是如何命名的。但同意,'這不是最好的命名。 –

+1

我使用'self',但最近發現這是與WebWorkers中頂級屬性的名稱衝突。並不是說你不能有相同的名字,但它確實會讓事情混淆不清。另外,我發現'that'這個名字與'this'相反' – Matt

7

bind退房的MDN文件:https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Function/bind

使用此功能,您可以更改範圍(什麼this是):

Example.prototype.SetEvent = function(){ 
    this.bar.onclick = this.ClickEvent.bind(this); 
}; 

注意,但是,這是一個新增加到EMCA,因此可能不會在所有用戶代理中受支持。在上面鏈接的MDN文件中有一個pollyfill。

3

bind的問題是,是only supported by IE9+

該功能可與es5-shim被polyfilled,但它不完全等同於本機實現:

  • 警告:綁定功能,有一個原型屬性。
  • 警告:綁定功能,不要試圖太硬,讓你從他們的操作和arguments性能caller
  • 警告:綁定函數在callapply中沒有檢查,以避免作爲構造函數執行。

另一種方法可以jQuery.proxy

$(elem).on('click', $.proxy(eventHandler, this)); 

這是更有益的,如果你想以後刪除事件處理程序,因爲當一個函數穿過proxy方法,jQuery的生成一個新的guid值,然後將該guid應用於核心函數以及生成的代理函數,以便您可以使用原始函數引用來解除已被代理的事件處理函數回調:

$(elem).off('click', eventHandler); 
+0

'.bind( )'不會比'$ .proxy'完全跨瀏覽器。它基本上是'.bind()'的非標準版本。如果您列出的警告實際上是一個問題,那麼'$ .proxy'將不會更好。更何況這個問題很明顯,他不能使用jQuery。 – 2015-03-31 21:07:30

+0

@squint我建議使用'$ .proxy'(或類似的實現),因爲它是一個鬆散的連接,這對OO事件處理非常有幫助。但是,謝謝你,我會更新我的答案,因爲正如你所說的,一個polyfilled的'.bind()'和'$ .proxy'完全不同。 –

0

其他解決方案:使用ES6引入的「箭頭函數」。那些具有不改變上下文的特殊性,IE什麼this指向。這裏有一個例子:

function Foo(){ 
    myeventemitter.addEventListener("mousedown", (()=>{ 
     return (event)=>{this.myinstancefunction(event)}; /* Return the arrow 
function (with the same this) that pass the event to the Foo prototype handler */ 
    })()); 
} 
Foo.prototype.myinstancefunction = function(event){ 
    // Handle event in the context of your Object 
} 

Arrow function specs @ MDN

編輯

要當心它。如果您在客戶端使用它,並且無法確定JS解釋器的功能,請注意舊瀏覽器將無法識別箭頭功能(see CanIUse stats)。只有當你知道什麼會運行它時才使用這種方法(最近的瀏覽器只有& NodeJS應用程序)

相關問題