Використання jQuery $ (this) з функціями стрілки ES6 (лексична ця прив'язка)


129

Використання функцій стрілок 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'); }
    });
  }
}

Потім $(this)перетворюється на закриття типу ES5 (self = this).

Чи є спосіб змусити Трасера ​​ігнорувати "$ (це)" для лексичного зв’язування?


це здається ідеальним прикладом, коли не використовувати функцію стрілки, оскільки .on()дійсно має thisкорисне для вас значення. Для мене набагато зрозуміліше thisпосилатися на ціль події, ніж передати подію та знайти ціль вручну. Я не дуже багато грав з функціями стрілок, але здається, було б заплутано повертатися назад і назад з анонімними функціями.
robisrob

Відповіді:


194

Це не має нічого спільного з 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.


4
Зауважте, що насправді це розбіжність лише для делегованих .onдзвінків . thisevent.currentTarget
loganfsmyth

Це відповідь у порядку? Як зазначав loganfsmyth, this== event.currentTarget. Немає?
Леон Пелтьє

3
@ LéonPelletier № thisі event.currentTargetє такими ж, якщо вони thisне прив'язані до області, що додається, як у функції стрілки ES6.
meagar

8
якщо ви хочете зберегти якийсь код, ви також можете його знищити: ({currentTarget}) => {$ (currentTarget) .addClass ('active')}
Франк

55

Прив'язка події

$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
});

Шукаєте $jQueryElements.each()? jQuery насправді надсилає деякі аргументи до кожного об’єкта, тому вам це взагалі не потрібно => Це$(...).each((index, el) => console.log(el))
jave.web

53

Інший випадок

Верхня відповідь правильна, і я її проголосував.

Однак є й інший випадок:

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

Неможливо виправити як:

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

Це історична помилка jQuery, яка ставить індекс замість елемента в якості першого аргументу:

.each (функція)


Тип функції : Function( Integer index, Element element )
Функція для виконання кожного відповідного елемента.

Дивіться: https://api.jquery.com/each/#each-function


1
Те саме для fucntions, як$('jquery-selector').map
Ніколас

Це було дуже корисно мені використовувати в таких речах, як $ ('jquery-selector'). Фільтрувати і т. Д. ... дякую, що зробив це так зрозуміло.
R Jones

8

(Це відповідь, яку я написав для іншої версії цього питання, перш ніж дізнатися, що це дублікат цього питання. Я думаю, що відповідь досить чітко збирає інформацію, тому я вирішив додати її як вікі спільноти, хоча це значною мірою просто інше формулювання інших відповідей.)

Ви не можете. Це половина точки функцій стрілок, вони закриваються thisзамість того, щоб мати власну, встановлену тим, як їх називають. У випадку використання у запитанні, якщо ви хочете thisвстановити jQuery при виклику обробника, обробник повинен бути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під час виклику вашого обробника.


5

Як сказав Мегер у своїй відповіді на це ж запитання. Якщо ви хочете написати 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 у відповіді @ Meager , і я вважав її корисною, і я думаю, що не всі люди прочитають цей коментар, тому я написав його як цю іншу відповідь.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.