在 javascript 原型事件处理程序中保留“this”引用
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/8100469/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Preserve 'this' reference in javascript prototype event handler
提问by George Hess
What is the correct way to preserve a this
javascript reference in an event handler stored inside the object's prototype? I'd like to stay away from creating temp vars like '_this' or 'that' and I can't use a framework like jQuery. I saw a lot of people talk about using a 'bind' function but was unsure of how to implement it in my given scenario.
this
在存储在对象原型内的事件处理程序中保留javascript 引用的正确方法是什么?我想远离创建像“_this”或“that”这样的临时变量,而且我不能使用像 jQuery 这样的框架。我看到很多人谈论使用“绑定”功能,但不确定如何在我给定的场景中实现它。
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'
};
回答by Tomasz Nurkiewicz
I find bind()
being the cleanest solution so far:
我发现这bind()
是迄今为止最干净的解决方案:
this.bar.onclick = this.ClickEvent.bind(this);
BTW the otherthis
is called that
by convention very often.
顺便说一句,另一个经常被惯例this
称为that
。
回答by Chris Baker
Check out the MDN document on bind
: https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Function/bind
查看 MDN 文档bind
:https: //developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Function/bind
Using this functionality, you can change the scope (what this
is):
使用此功能,您可以更改范围(是什么this
):
Example.prototype.SetEvent = function(){
this.bar.onclick = this.ClickEvent.bind(this);
};
Be aware, however, that this is a new addition to EMCA and thus may not be supported in all user agents. There is a pollyfill available at the MDN document linked above.
但是请注意,这是 EMCA 的新增功能,因此可能并非所有用户代理都支持。上面链接的 MDN 文档中有一个 pollyfill。
回答by Paolo Moretti
The problem with bind
is that is only supported by IE9+.
问题bind
是只有 IE9+ 支持。
The function can be polyfilled with es5-shim
, but it's not completely identical to the native implementation:
该函数可以用 填充es5-shim
,但它与本机实现并不完全相同:
- Caveat: the bound function has a prototype property.
- Caveat: bound functions do not try too hard to keep you from manipulating their
arguments
andcaller
properties.- Caveat: bound functions don't have checks in
call
andapply
to avoid executing as a constructor.
- 警告:绑定函数有一个原型属性。
- 警告:绑定函数不要太努力阻止你操纵它们的
arguments
和caller
属性。- 警告:绑定函数没有签入
call
并apply
避免作为构造函数执行。
Another alternative can be jQuery.proxy
:
另一种选择可以是jQuery.proxy
:
$(elem).on('click', $.proxy(eventHandler, this));
This is even more helpful if you want to remove the event handler later, because when a function goes through the proxy
method, jQuery generates a new guid value and then applies that guid to both the core function as well as the resultant proxy function, so that you can use the original function reference to unbind an event handler callback that has been proxied:
如果您想稍后删除事件处理程序,这会更有帮助,因为当一个函数通过该proxy
方法时,jQuery 会生成一个新的 guid 值,然后将该 guid 应用于核心函数以及结果代理函数,以便您可以使用原始函数引用来解除已代理的事件处理程序回调的绑定:
$(elem).off('click', eventHandler);
回答by Alexandre Germain
Other solution: use the "arrow functions" introduced by ES6. Those have the particularity to not change the context, IE what this
points to. Here is an example:
其他解决方案:使用 ES6 引入的“箭头函数”。那些具有不改变上下文的特殊性,IEthis
指向什么。下面是一个例子:
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
}
Edit
编辑
Be carefull with it. If you use it client-side and you can't be sure of the capabilities of the JS interpreter, note that old browser won't recognize arrow functions (see CanIUse stats). Use this method only if you KNOW what will run it (recent browsers only & NodeJS apps)
小心点。如果您在客户端使用它并且无法确定 JS 解释器的功能,请注意旧浏览器将无法识别箭头函数(请参阅 CanIUse stats)。仅当您知道将运行它的内容时才使用此方法(仅限最近的浏览器和 NodeJS 应用程序)