将 jQuery $(this) 与 ES6 箭头函数一起使用(词法 this 绑定)

Using jQuery $(this) with ES6 Arrow Functions (lexical this binding)

提问人:JRodl3r 提问时间:12/28/2014 最后编辑:isherwoodJRodl3r 更新时间:9/13/2022 访问量:83076

问:

将 ES6 箭头函数与词法绑定一起使用非常棒。this

但是,我刚才遇到了一个问题,将它与典型的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'); }
    });
  }
}

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

有没有办法让 Traceur 忽略“$(this)”进行词法绑定?

javascript jquery ecmascript-6 箭头函数

评论

1赞 robisrob 5/23/2017
这似乎是何时不使用箭头函数的完美示例,因为确实有一个对您有用的值。对我来说,引用事件目标比必须传递事件并手动查找目标要清晰得多。我没有玩过太多箭头函数,但似乎来回使用匿名函数会令人困惑。.on()thisthis

答:

244赞 user229044 12/28/2014 #1

这与 Traceur 和关闭某些东西无关;这就是 ES6 的工作方式。这是您通过使用而不是 .=>function () { }

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

解决此特定问题的方法不是用于访问单击的元素,而是使用:thisevent.currentTarget

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

jQuery之所以提供,是因为即使在ES6之前,jQuery也并不总是能够对回调函数施加一个(即,如果它通过bind绑定到另一个上下文。event.currentTargetthis

评论

5赞 loganfsmyth 12/28/2014
请注意,虽然它只对委托调用发散,但实际上是 ..onthisevent.currentTarget
0赞 Léon Pelletier 7/9/2016
这个答案可以吗?正如 loganfsmyth 所指出的,== .不?thisevent.currentTarget
4赞 user229044 7/15/2016
@LéonPelletier 编号 并且相同,除非绑定到封闭范围,就像 ES6 箭头函数一样。thisevent.currentTargetthis
14赞 Frank 3/24/2018
如果想保存一些代码,也可以解构它: ({currentTarget}) => { $(currentTarget).addClass('active') }
3赞 T.J. Crowder 11/4/2022
“如果你想写ES6,你需要一直写ES6。”那是。。。。一个非常可疑的陈述。ES2015+是完全向后兼容的(除了少数非常极端的情况)。你可以混合和分配给 上的东西,以选择一个随机的例子。你可以继续使用(尽管我不会),或者使用这个东西而不是箭头函数(尽管我不会)。等。你不能做的是同时用于两种不同的东西。:-)class XX.prototypevarvar x = this;this
71赞 Ryan Huang 12/10/2015 #2

事件绑定

$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
});
9赞 T.J. Crowder #3

(这是我为这个问题的另一个版本写的答案,在得知它是这个问题的重复之前。我认为答案相当清楚地汇集了信息,所以我决定将其添加为社区维基,尽管它在很大程度上只是其他答案的不同措辞。

你不能。这是箭头函数的一半,它们关闭而不是拥有自己的,这是由它们的调用方式设置的。对于问题中的用例,如果希望在调用处理程序时由 jQuery 设置,则处理程序需要是一个函数。thisthisfunction

但是,如果你有理由使用箭头(也许你想用它来表达箭头之外的意思),你可以用,而不是如果你喜欢的话:thise.currentTargetthis

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

on 事件对象与 jQuery 在调用处理程序时设置的对象相同。currentTargetthis

68赞 Tyler Liu 3/27/2017 #4

另一个案例

meagar 的答案是正确的,我已经投了赞成票。

但是,还有另一种情况:

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

可以固定为:

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

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

.each( 函数 )

function
Type:
要为每个匹配元素执行的函数。
Function( Integer index, Element element )

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

同时适用于 和 。.map( function ).filter( function )

评论

0赞 st3phhays 9/15/2022
啊哈!这帮我省去了一堆麻烦,谢谢!
10赞 Haritsinh Gohil 7/30/2019 #5

正如 Meager 在回答同一个问题时所说:如果你想写 ES6,你需要一直写 ES6,

所以如果你使用的是 ES6: 的箭头函数,那么你必须使用 代替 .(event)=>{}$(event.currentTarget)$(this)

您还可以使用更好、更干净的方式来使用 currentTarget,例如 ,({currentTarget})=>{}

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

最初,Rizzi Frank 在 Meagar 的回答中评论了这个想法,我觉得它很有用,我认为并非所有人都会阅读该评论,所以我将其写为另一个答案。