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