2011-11-11 86 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应用程序)

相关问题