在javascript原型事件处理程序中保留“this”引用

IT技术 javascript oop event-handling this
2021-03-13 19:34:50

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'
};
4个回答

我发现这bind()是迄今为止最干净的解决方案:

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

顺便说一句,另一个 经常被惯例this称为that

这当然不适用于旧的 IE(8 及以上)
2021-04-17 19:34:50
实际上,我讨厌创建this引用,无论它们如何命名。但同意,that这不是最好的命名。
2021-04-28 19:34:50
讨厌创建对这个称为“那个”(a la Crockford)的引用。我更喜欢“实例”(a la Stefanov)或“我”(a la ExtJS)
2021-04-30 19:34:50
@GeorgeJempty 这只是个人喜好
2021-05-03 19:34:50
我使用“self”,但最近发现与 WebWorkers 中的顶级属性发生名称冲突。并不是说你不能有相同的名字,但它确实混淆了事情。另外,我发现名称“that”与“this”完全相反
2021-05-13 19:34:50

查看 MDN 文档bindhttps : //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。

问题bind只有 IE9+ 支持

该函数可以用 填充es5-shim,但它与本机实现并不完全相同:

  • 警告:绑定函数有一个原型属性。
  • 警告:绑定函数不要太努力阻止你操纵它们的argumentscaller属性。
  • 警告:绑定函数没有签入callapply避免作为构造函数执行。

另一种选择可以是jQuery.proxy

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

如果您想稍后删除事件处理程序,这会更有帮助,因为当一个函数通过该proxy方法时,jQuery 会生成一个新的 guid 值,然后将该 guid 应用于核心函数以及结果代理函数,以便您可以使用原始函数引用来解除已代理的事件处理程序回调的绑定:

$(elem).off('click', eventHandler);
.bind()不亚于完全跨浏览器$.proxy它基本上是.bind(). 如果您列出的警告实际上是一个问题,那么$.proxy不会更好。更不用说问题很明显他不能使用jQuery。
2021-04-27 19:34:50
@squint 我建议使用$.proxy(或类似的实现),因为它是一个松散的连接,这在 OO 事件处理中非常有用。但是谢谢你,我会更新我的答案,因为,就像你说的,polyfill 的.bind()跨浏览器不亚于$.proxy.
2021-05-07 19:34:50

其他解决方案:使用 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
}

箭头函数规范@MDN

编辑

小心点。如果您在客户端使用它并且无法确定 JS 解释器的功能,请注意旧浏览器将无法识别箭头函数(请参阅 CanIUse stats)。仅当您知道将运行它的内容时才使用此方法(仅限最近的浏览器和 NodeJS 应用程序)