Соответствуют ли 'Стрелочные функции' и 'Функции' или они взаимозаменяемы?
Проблема с использованием стрелочных функций в ES2015
С введением стрелочных функций в ES2015 появилась возможность использовать более лаконичный синтаксис для определения функций. Однако у меня возникли следующие вопросы:
- Могу ли я заменить все свои объявленные функции/выражения на стрелочные функции?
- На что мне следует обратить внимание при этом?
Примеры
Конструктор функции
function User(name) {
this.name = name;
}
// против
const User = name => {
this.name = name;
};
Методы прототипа
User.prototype.getName = function() {
return this.name;
};
// против
User.prototype.getName = () => this.name;
Методы объекта (литерал)
const obj = {
getName: function() {
// ...
}
};
// против
const obj = {
getName: () => {
// ...
}
};
Обратные вызовы
setTimeout(function() {
// ...
}, 500);
// против
setTimeout(() => {
// ...
}, 500);
Функции с произвольным числом аргументов
function sum() {
let args = [].slice.call(arguments);
// ...
}
// против
const sum = (...args) => {
// ...
};
Вопросы
Какие потенциальные проблемы могут возникнуть при такой замене? Например, как поведение this
изменяется в стрелочных функциях, и есть ли еще какие-то аспекты, которые необходимо учитывать?
2 ответ(ов)
Arrow функции ⇒ лучшее новшество ES6 на сегодняшний день. Это действительно мощное дополнение к ES6, которое я использую постоянно.
Но подождите, нельзя использовать стрелочные функции повсеместно в вашем коде. Они не работают во всех случаях, например, с this
, где стрелочные функции не применимы. Безусловно, стрелочные функции — это отличное дополнение, которое упрощает код.
Однако вы не можете использовать стрелочную функцию, когда необходим динамический контекст: при определении методов, создании объектов с конструкторами или получении целевого объекта через this
при обработке событий.
Когда не следует использовать стрелочные функции:
У них нет
this
Они используют «лексическое связывание», чтобы определить, каково значение «
this
». Проще говоря, лексическое связывание использует «this
» из тела функции.У них нет
arguments
Стрелочные функции не имеют объекта
arguments
. Однако ту же функциональность можно достичь с помощью параметров rest.let sum = (...args) => args.reduce((x, y) => x + y, 0); sum(3, 3, 1) // вывод: 7
Их нельзя использовать с
new
Стрелочные функции не могут быть конструкторами, поскольку у них нет свойства prototype.
Когда использовать стрелочные функции, а когда нет:
- Не используйте для добавления функции как свойства в литерал объекта, потому что мы не можем получить доступ к
this
. - Функциональные выражения лучше подходят для методов объекта. Стрелочные функции лучше использовать для обратных вызовов или методов, таких как
map
,reduce
илиforEach
. - Используйте функциональные объявления для функций, которые вы будете вызывать по имени (поскольку они подняты).
- Используйте стрелочные функции для обратных вызовов (поскольку они, как правило, короче).
Не всегда можно использовать стрелочные функции вместо обычных функций. Вот пример, когда это нельзя сделать.
Стрелочные функции НЕЛЬЗЯ использовать как конструкторы
Кратко:
Это связано с тем, как стрелочные функции обрабатывают ключевое слово this. JavaScript выбросит ошибку, если вы попытаетесь вызвать стрелочную функцию как "конструктор". Для решения этой проблемы используйте обычные функции.
Подробное объяснение:
Поскольку конструкторы объектов зависят от ключевого слова this, которое может изменяться.
В общем случае, this всегда ссылается на глобальный объект (в браузере это объект window).
НО, когда вы делаете что-то вроде этого:
function personCreator(name) {
this.name = name;
}
const person1 = new personCreator('John');
Ключевое слово new делает свою магию, и this внутри personCreator становится пустым объектом, а не ссылается на глобальный объект. После этого создается новое свойство name внутри этого пустого объекта this, и его значение будет 'John'. В конце, возвращается объект this.
Как мы видим, ключевое слово new изменило значение this с глобального объекта на пустой объект .
Стрелочные функции не позволяют изменять свой объект this. Их this всегда ссылается на область, в которой они были статически созданы. Это называется статическая лексическая область. Вот почему вы не можете использовать методы bind, apply или call со стрелочными функциями. Итак, их this "заперт" на значение this той области, в которой они были созданы. Это сделано специально.
По этой причине стрелочные функции не могут использоваться как "конструкторы".
Примечание:
Лексическая область — это просто область, в которой функция была создана. Например:
function personCreator(name) {
this.name = name;
const foo = () => {
const bar = () => {
console.log(this); // Вывод: { name: 'John' }
}
console.log(this); // Вывод: { name: 'John' }
bar();
}
foo();
}
const person1 = new personCreator('John');
Лексическая область bar — это всё, что находится внутри foo. Таким образом, значение this у bar такое же, как у foo, то есть соответствует значению this у personCreator.
ECMAScript 6: Стрелочная функция, возвращающая объект
Может ли выражение (a == 1 && a == 2 && a == 3) когда-либо оцениться как истинное?
Синтаксис асинхронной стрелочной функции
Как клонировать объект JavaScript, исключив один ключ?
Как обновить вложенные свойства состояния в React