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

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

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

1) Обработчики событий

Предположим, что у вас есть следующее текстовое поле ввода:

<input type="text" name="username" id="username" placeholder="Enter a username">

И вы хотите показывать приветственное сообщение, когда пользователи вводят свои имена пользователей. Ниже показан элемент <div>, который будет отображать приветственное сообщение:

<div id="greeting"></div>

Как только пользователи вводят свои имена пользователей, вы фиксируете текущее значение ввода и обновляете его до элемента <div>:

const greeting = document.querySelector('#greeting');
const username = document.querySelector('#username');
username.addEventListener('keyup', () => {
  greeting.textContent = 'Hello ' + this.value;
});

Однако при выполнении кода вы получите следующее сообщение независимо от того, что вы введете:

Hello undefined

Это означает, что this.value в обработчике событий всегда возвращает значение undefined.

Как упоминалось ранее, стрелочная функция не имеет собственного значения this. Она использует значение this объемлющей лексической области. В приведенном выше примере функция со стрелкой this in ссылается на глобальный объект.

В веб-браузере глобальным объектом является window. Объект window не имеет свойства value. Поэтому движок JavaScript добавляет свойство value к объекту window и устанавливает для него значение undefined.

Чтобы решить эту проблему, вам нужно использовать обычную функцию. this значение будет привязано к элементу <input>, который запускает событие.

username.addEventListener('keyup', function() { 
    input.textContent = 'Hello ' + this.value; 
});

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

См. следующий объект counter :

const counter = {
    count: 0,
    next: () = > ++this.count,
    current: () = >
    this.count
};

Объект counter имеет два метода: current() и next(). Метод current() возвращает текущее значение счетчика, а метод next() возвращает следующее значение счетчика.

Ниже показано следующее значение счетчика, которое должно быть равно 1:

console.log(counter.next());

Однако он возвращает NaN.

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

this.count внутри метода next() эквивалентен window.count(в веб-браузере).

По умолчанию значение window.count не undefined, поскольку объект window не имеет свойства count. Метод next() добавляет единицу к undefined, что приводит к NaN.

Чтобы исправить это, вы используете обычные функции в качестве метода литерала объекта следующим образом:

const counter = {
    count: 0,
    next() {
        return ++this.count;
    },
    current() {
        return this.count;
    }
};

Теперь вызов метода next() вернет единицу, как и ожидалось:

console.log(counter.next());
 // 1

3) Методы-прототипы

См. следующий объект Counter, использующий шаблон prototype :

function Counter() {
    this.count = 0;
}

Counter.prototype.next = () => {
    return this.count;
};

Counter.prototype.current = () => {
    return ++this.next;
}

Значение this в этих методах next() и current() ссылается на глобальный объект. Поскольку вы хотите, чтобы this значение внутри методов ссылалось на объект Counter, вместо этого вам нужно использовать обычные функции:

function Counter() {
    this.count = 0;
}

Counter.prototype.next = function () {
    return this.count;
};

Counter.prototype.current = function () {
    return ++this.next;
}

4) Функции, использующие объект arguments

Стрелочные функции не имеют объекта arguments. Поэтому, если у вас есть функция, которая использует объект arguments, вы не можете использовать функцию стрелки.

Например, следующая функция concat() не будет работать:

const concat = (separator) => {
    let args = Array.prototype.slice.call(arguments, 1);
    return args.join(separator);
}

Вместо этого вы используете обычную функцию, подобную этой:

function concat(separator) {
    let args = Array.prototype.slice.call(arguments, 1);
    return args.join(separator);
}

Заключение

  • Стрелочная функция не имеет собственного значения this. Вместо этого она использует значение this объемлющей лексической области. У стрелочной функции также нет объекта arguments.
  • Избегайте использования функции стрелки для обработчиков событий, методов объекта, методов прототипа и функций, использующих объект arguments.
Рейтинг
( Пока оценок нет )
Александр Русаков / автор статьи
Программист, разработчик, 12 лет опыта работы в крупных компаниях. Быстро освоил typescript, делюсь своими знаниями на страницах этого сайта.
Загрузка ...
JavaScript и TypeScript