Три примера, когда не стоит использовать стрелочные функции JavaScript


Стрелочные функции ES6

Вы их знаете, любите и наверняка постоянно используете! Представленные в 2015 году как часть обновления ECMAScript 6 стрелочные функции приобрели свою популярность совершенно заслуженно. Их синтаксис  —  прекрасный синтаксический сахар, устраняющий необходимость в: 

  • ключевом слове return (для однострочных функций);
  • ключевом слове function;
  • фигурных скобках.

Стрелочные функции также разрешили некоторые сложности, связанные с областью видимости функций JavaScript, а также с ключевым словом this, ведь иногда всё, что вам нужно, это анонимная функция. 

Как было сказано выше, стрелочные функции не являются универсальным решением для всех задач, с которыми вы сталкиваетесь при написании функций JavaScript. Давайте рассмотрим несколько ситуаций, в которых стрелочные функции являются не самым удачным решением. 

Методы объекта

Допустим, вы хотите создать метод для привязки к объекту:

const mario = { lives: 3, oneUp: () => { this.lives++; } }

В этом примере при вызове mario.oneUp() мы ожидаем, что значение mario.lives увеличится с 3 до 4. Однако значение lives останется неизменным независимо от того, сколько раз вызван oneUp(). Почему? Вот ответ — this!

Согласно MDN:

Стрелочная функция не имеет собственного this. Используется значение this объемлющей лексической области видимости; стрелочные функции подчиняются стандартным правилам поиска переменных. Таким образом, при поиске this, которого нет в текущей области видимости, стрелочная функция прервётся при нахождении this из объемлющей области видимости. 

В нашем случае объемлющим контекстом будет объект window. При вызове oneUp() программа будет запрашивать увеличение значения lives в объекте window. Такого значения не существует, поэтому код не работает. 

Вместо этого используем синтаксис традиционной функции, который свяжет this функции с определённым объектом, вызывающим функцию: 

const mario = { lives: 3, oneUp: function() { this.lives++; } };

Прототип объекта

Фрагмент JavaScript, с которым мы будем работать в этом примере: 

class Robot { constructor(name, catchPhrase) { this.name = name; this.catchPhrase = catchPhrase; } }; Robot.prototype.speak = () => { console.log(this === window); return this.catchPhrase }; const ironG = new Robot("Iron Giant", "Be good"); ironG.speak();

Вызов функции в строке 15 будет выглядеть так:

true undefined

Мы определили функцию прототипа speak() и передали в качестве ключевой фразы для нового объекта Robot, так почему же код выдал undefined?

console.log() показывает почему. Как видим в консоли, если (this === window), то выводится true, предоставляя доказательства того, что мы обсуждали в предыдущем примере с методами объекта. 

При работе с функциями, требующими контекста, стоит использовать обычный синтаксис функции для правильного связывания this

Robot.prototype.speak = function() { console.log(this === ironG); // true return this.catchphrase; };

Динамический контекст

Вот последний пример:

const button = document.querySelector(#darkMode); button.addEventListener('click', () => { this.classList.toggle('on'); });

Но сейчас вы, вероятно, знаете, что код не будет работать и почему. Я дам вам подсказку: причина вновь связана с this.

При объявлении функции синтаксис стрелочной функции связывает контекст статически, что прямо противоположно тому, чего мы пытаемся достичь при работе с обработчиками или слушателями событий, которые по своей природе являются динамическими

При манипуляциях DOM с помощью обработчиков или слушателей инициируемые события указывают на принадлежность this целевому элементу.

Для стрелочной функции, определённой в глобальном контексте выполнения, this будет указывать на window. Значит, в коде выше this.classList будет преобразован в window.classList, что приведёт к TypeError.

Вот и всё!

Я надеюсь, что примеры были просты и понятны. Если нет, я рекомендую почитать подробнее про this в JavaScript, чтобы разобраться, когда стоит использовать стрелочные функции, а когда нет. 


Перевод статьи Andrew Koenig-Bautista: 3 Examples of When Not to Use JavaScript Arrow Functions


Поделиться статьей:


Вернуться к статьям

Комментарии

    Ничего не найдено.