JavaScript: преимущества стрелочных функций
Возможно, вы не знаете, что это одно из основных различий между обычными и стрелочными функциями ES6 в JavaScript.

Когда я был в учебном лагере по программированию, изучая JavaScript и ES6, казалось, что у всех в классе была некоторая путаница по поводу обычных объявлений функций и новых объявлений стрелочных функций ES6.
- Когда нам следует использовать обычные функции, а когда стрелочные функции?
- В чем разница между обычными функциями и стрелочными функциями?
- Можем ли мы использовать одно или другое во всех ситуациях для единообразия?
Проведя небольшое исследование, я обнаружил, что обычные функции и стрелочные функции в определенных обстоятельствах фактически не взаимозаменяемы. Помимо синтаксиса, обычные функции и стрелочные функции имеют еще одно важное отличие, которое заключается в способе привязки ключевого слова this.
Давайте рассмотрим очень простой пример. Предположим что, у нас есть следующий объект JavaScript:
const obj1 = {
fullName: 'Object 1',
color: 'red',
print: function() {
console.log(`${this.fullName} is ${this.color}`);
}
};
obj1.print(); // Object 1 is red
У нас есть метод print
для obj1
, который выводит строку в консоль. Результат - то, что, как мы и ожидали, this
в методе print
ссылается на сам obj1
.
Теперь давайте создадим еще один объект с немного другим методом print
:
const obj2 = {
fullName: 'Object 2',
color: 'blue',
print: function() {
setTimeout(function() {
console.log(`${this.fullName} is ${this.color}`);
}, 1000);
}
};
obj2.print(); // undefined - is undefined
Теперь метод print
будет выводить полученную строку только через одну секунду из-за setTimeout
. Но почему undefined is undefined
вместо вывода Object 2 is blue
?
Ответ заключается в объявлении функции, которую мы передали в качестве обратного вызова setTimeout
. Обычное объявление функции создает область действия, и любое использование this
внутри функции будет относиться к непосредственному родительскому объекту, которому принадлежит функция.
В приведенном выше фрагменте кода в строке 5 анонимная функция, объявленная с использованием обычного объявления функции, передается как обратный вызов для setTimeout
. Затем два this
в строке 6 будут ссылаться на объект, которому принадлежит метод setTimeout
, который переходит в объект window
.
Поскольку свойства fullName
и color
не существуют в объекте window
, результирующая строка возвращает undefined is undefined
.
Как мы можем сделать так, чтобы два this
в строке 6 ссылались на obj2
? На этот раз давайте объявим функцию обратного вызова в строке 5, используя синтаксис стрелочной функции ES6:
const obj2 = {
fullName: 'Object 2',
color: 'blue',
print: function() {
setTimeout(() => {
console.log(`${this.fullName} is ${this.color}`);
}, 1000);
}
};
obj2.print(); // Object 2 is blue
Это работает! Так какова же теория этого изменения?
Что ж, оказывается, что объявление стрелочной функции создает то, что мы называем лексической областью видимости. Это означает, что два this в строке 6 будут ссылаться не на свой непосредственный родительский объект, а на вызывающий, который вызвал функцию, содержащую их.
В строке 11 при вызове obj2 метода print все элементы this, заключенные внутри стрелочных функций метода print, будут ссылаться на obj2.
Заключение
Я надеюсь, что эта статья объяснила необходимые концепции и помогла вам разобраться с путаницей. Ключевое слово this в JavaScript целая тема сама по себе, и есть много дискуссий об этом, но документация MDN является хорошей отправной точкой для дальнейших исследований.