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



Книга Три примера, когда не стоит использовать стрелочные функции 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, чтобы разобраться, когда стоит использовать стрелочные функции, а когда нет. 




476   0  

Comments

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