使用 jQuery $(this)和 ES6箭头函数(lexical this binding)

使用带有词法 this绑定的 ES6箭头函数非常好。

但是,我刚才在使用它时遇到了一个问题,那就是典型的 jQuery 单击绑定:

class Game {
foo() {
self = this;
this._pads.on('click', function() {
if (self.go) { $(this).addClass('active'); }
});
}
}

改为使用箭头函数:

class Game {
foo() {
this._pads.on('click', () => {
if (this.go) { $(this).addClass('active'); }
});
}
}

然后将 $(this)转换为 ES5(self = this)类型闭包。

是让 Traceur 忽略词法绑定的“ $(this)”的一种方法吗?

77232 次浏览

这与 Traceur 和关闭某些东西没有任何关系; 这就是 ES6的工作原理。这就是使用 =>而不是 function () { }所要求的特定功能。

如果你想写 ES6,你需要一直写 ES6。您不能在特定的代码行上切换进出它,而且您绝对不能抑制或改变 =>的工作方式。即使你可以,你也只会得到一些只有你才能理解的奇怪的 JavaScript 版本,而且在你定制的 Traceur 之外,它们永远不会正常工作,这绝对不是 Traceur 的意义所在。

解决这个特殊问题的方法不是使用 this获得对单击元素的访问权,而是使用 event.currentTarget:

Class Game {
foo(){
this._pads.on('click', (event) => {
if(this.go) {
$(event.currentTarget).addClass('active');
}
});
}
}

JQuery 特别提供了 event.currentTarget,因为即使在 ES6之前,jQuery 也不可能总是在回调函数上强加一个 this(例如,如果它通过 bind绑定到另一个上下文)。

事件绑定

$button.on('click', (e) => {
var $this = $(e.currentTarget);
// ... deal with $this
});

循环

Array.prototype.forEach.call($items, (el, index, obj) => {
var $this = $(el);
// ... deal with $this
});

(这是我为这个问题的另一个版本写的答案,在得知它是这个问题的复制品之前。我认为这个答案把信息整合得相当清楚,所以我决定把它作为一个社区维基添加进去,尽管它很大程度上只是其他答案的不同措辞。)

你不能。这是箭头函数的一半,它们在 this上关闭,而不是由它们的调用方式设置。对于问题中的用例,如果您希望在调用处理程序时由 jQuery 设置 this,那么处理程序将需要是一个 function函数。

但是,如果您有使用箭头的理由(也许您想使用 this表示箭头之外的含义) ,您可以使用 e.currentTarget而不是 this,如果您愿意:

class Game {
foo(){
this._pads.on('click', e => {                   // Note the `e` argument
if(this.go) {
$(e.currentTarget).addClass('active');      // Using it
}
});
}
}

事件对象上的 currentTarget与 jQuery 在调用处理程序时将 this设置为的 currentTarget相同。

另一个案子

Meagar 的答案是正确的,我投了反对票。

然而,还有另一种情况:

$('jquery-selector').each(() => {
$(this).click();
})

可定义为:

$('jquery-selector').each((index, element) => {
$(element).click();
})

这是 jQuery 中的一个历史性错误,它将 索引而不是 元素作为第一个参数:

。每个(功能)

功能
类型: Function( Integer index, Element element )
为每个匹配的元素执行的函数。

见: https://api.jquery.com/each/#each-function

也适用于 .map( function ).filter( function )

正如 Meager在回答同一个问题时所说的,

因此,如果您使用 ES6: (event)=>{}的箭头函数,那么您必须使用 $(event.currentTarget)而不是 $(this)

你也可以使用更好更干净的方式来使用 currentTarget 作为 ({currentTarget})=>{},

Class Game {
foo(){
this._pads.on('click', ({currentTarget}) => {
if(this.go) {
$(currentTarget).addClass('active');
}
});
}
}

最初这个想法是评论的 Rizzi Frank在 meagar 的答案,我觉得它有用,我认为不是所有的人都会阅读这个评论,所以我写了这个另一个答案。