简体   繁体   English

使用 jQuery $(this) 和 ES6 箭头函数(词法 this 绑定)

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

Using ES6 arrow functions with lexical this binding is great.使用带有词法this绑定的 ES6 箭头函数非常棒。

However, I ran into an issue a moment ago using it with a typical jQuery click binding:但是,我刚才在使用典型的 jQuery 点击绑定时遇到了一个问题:

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

Using an arrow function instead:使用箭头 function 代替:

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

And then $(this) gets converted to ES5 (self = this) type closure.然后$(this)被转换为 ES5 (self = this) 类型的闭包。

Is a way to have Traceur ignore "$(this)" for lexical binding?是一种让 Traceur 忽略词法绑定的“$(this)”的方法吗?

This has nothing to do with Traceur and turning something off, this is simply how ES6 works.这与 Traceur 和关闭某些东西无关,这就是 ES6 的工作原理。 It's the specific functionality you're asking for by using => instead of function () { } .这是您通过使用=>而不是function () { }来要求的特定功能。

If you want to write ES6, you need to write ES6 all the time, you can't switch in and out of it on certain lines of code, and you definitely cannot suppress or alter the way => works.如果你想写 ES6,你需要一直写 ES6,你不能在某些代码行中切换进出它,你绝对不能抑制或改变=>的工作方式。 Even if you could, you would just wind up with some bizarre version of JavaScript that only you understand and which would never work correctly outside of your customized Traceur, which definitely isn't the point of Traceur.即使可以,您最终也会得到一些只有您自己理解的奇怪版本的 JavaScript,并且在您定制的 Traceur 之外永远无法正常工作,这绝对不是 Traceur 的重点。

The way to solve this particular problem is not to use this to gain access to the clicked element, but instead use event.currentTarget :解决这个特定问题的方法不是使用this来访问被点击的元素,而是使用event.currentTarget

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

jQuery provides event.currentTarget specifically because, even before ES6, it is not always possible for jQuery to impose a this on the callback function (ie, if it was bound to another context via bind . jQuery 专门提供event.currentTarget是因为,即使在 ES6 之前,jQuery 也不总是可以对回调 function 施加this (即,如果它通过bind绑定到另一个上下文。

Event binding事件绑定

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

Loop环形

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

Another case另一个案例

The answer by meagar is correct and I've up-voted it. meagar 的答案是正确的,我投了赞成票。

However, there is another case:但是,还有另一种情况:

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

Could be fixed as:可以固定为:

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

This is a historical mistake in jQuery which puts the index , instead of the element as the first argument:这是 jQuery 中的一个历史错误,它将索引而不是元素作为第一个参数:

.each( function ) .每个(function)

function function
Type: Function( Integer index, Element element )类型: Function( Integer index, Element element )
A function to execute for each matched element.为每个匹配的元素执行一个 function。

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

(This is an answer I wrote for another version of this question, before learning it was a duplicate of this question. I think the answer pulls together the information fairly clearly so I decided to add it as a community wiki, although it's largely just different phrasing of the other answers.) (这是我为这个问题的另一个版本写的答案,在得知它是这个问题的副本之前。我认为答案相当清楚地汇总了信息,所以我决定将它添加为社区 wiki,尽管它在很大程度上只是不同其他答案的措辞。)

You can't.你不能。 That's half the point of arrow functions, they close over this instead of having their own that's set by how they're called.这是箭头函数的一半,它们关闭了this而不是拥有自己的,由它们的调用方式设置。 For the use case in the question, if you want this set by jQuery when calling the handler, the handler would need to be a function function.对于问题中的用例,如果您希望在调用处理程序时由this设置,则处理程序需要是function function。

But if you have a reason for using an arrow (perhaps you want to use this for what it means outside the arrow), you can use e.currentTarget instead of this if you like:但是如果你有使用箭头的理由(也许你想用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
      }
    });
  }
}

The currentTarget on the event object is the same as what jQuery sets this to when calling your handler.事件 object 上的currentTarget与调用处理程序时 jQuery 设置this相同。

As Meager said in his answer on this same question If you want to write ES6, you need to write ES6 all the time ,正如Meager在他对同一个问题的回答中所说,如果你想写 ES6,你需要一直写 ES6

so if you are using arrow function of ES6: (event)=>{} , then you have to use $(event.currentTarget) instead of $(this) .所以如果你使用 ES6 的箭头 function: (event)=>{} ,那么你必须使用$(event.currentTarget)而不是$(this)

you can also use more nicer and cleaner way of using currentTarget as ({currentTarget})=>{} ,您还可以使用更漂亮、更简洁的方式将 currentTarget 用作({currentTarget})=>{}

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

originally this idea was commented by rizzi frank in meagar's answer, and i felt it useful and i think that not all people will read that comment so i have written it as this another answer.最初, rizzi frank在 meagar 的回答中评论了这个想法,我觉得它很有用,我认为并非所有人都会阅读该评论,所以我把它写成另一个答案。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM