Курс →React JS

для начинающих
от платформы StackDev.ru

Стрелочные Функции JS - Arrow Functions (просто и с примерами)

Дата:
Javascript

Стрелочные функции (arrow functions) появились в 6-й редакции Javascript, более известной как ECMAScript 6. Сегодня их можно встретить практически в любом современном приложении, написанном на любом из современных JS фреймворков.

Я бы выделил 3 главных преимущества использования стрелочных функций:

  • Имеют более короткий и понятный синтаксис.
  • Позволяют использовать, так называемый, 'implicit return' (неявный) и писать функции с одной инструкцией в одну строчку
  • Принимает значение this из внешней функции (не создает собственный контекст исполнения)

Давайте разберем эти преимущества более детально.

Предположим у нас есть массив данных:

1const fruits = [‘apples’, ‘oranges’, ‘bananas’, ‘kiwi’];

Давайте используем метод .map(), чтобы пробежаться по нашему массиву, добавить к каждому значению слово 'fresh' и получить новый массив freshFruit:

1const fruits = ['яблоки', 'апельсины', 'бананы'];
2
3const freshFruits = fruits.map(function (fruit) {
4 return `свежие ${fruit}`;
5});
6console.log(freshFruits);
7// ['свежие яблоки', 'свежие апельсины', 'свежие бананы']

При выводе результата для каждого элемента исходного массива мы использовали обратные кавычки (backticks), которые позволяют совмещать написание строчных значений и переменных.

В этом примере мы использовали обычную функцию. Теперь давайте посмотрим, как будет выглядеть наше выражение, написанное с использованием стрелочной функции.

Cтрелочные Функции JS

Для начала давайте уберем слово function и добавим символ стрелочной функции =>. Таким образом мы получим выражение следующего вида:

1const fruits = ['яблоки', 'апельсины', 'бананы'];
2
3const freshFruits = fruits.map((fruit) => {
4 return `свежие ${fruit}`;
5});
6console.log(freshFruits);
7// ['свежие яблоки', 'свежие апельсины', 'свежие бананы']

Наша функция принимает один единственный аргумент – fruit. Следовательно, мы можем избавиться от скобок вокруг него.

Также мы можем использовать так называемый implicit return (подразумеваемое возвращение…). Явное возвращение (explicit return) подразумевает использование слова return при возврате результата. Если ваша функция возвращает какой-то один результат, то написание слова return можно опустить.

В результате получаем:

1const fruits = ['яблоки', 'апельсины', 'бананы'];
2
3// Убрали скобки вокруг fruit и слово return
4const freshFruits = fruits.map((fruit) => `свежие ${fruit}`);
5console.log(freshFruits);
6// ['свежие яблоки', 'свежие апельсины', 'свежие бананы']

Что мы изменили?

  • Удалили слово return
  • Записали все выражение в одну строчку
  • Удалили фигурные {} скобки

После удаления слова return и фигурных скобок мы получаем implicit return, и нам не требуется уточнять, что наша функция возвращает fresh ${fruit} (это предполагается).

Что eсли стрелочная функция не принимает никаких аргументов?

В случаях, когда в функцию не требуется передавать никаких аргументов необходимо оставлять пустые скобки:

1const fruits = ['яблоки', 'апельсины', 'бананы'];
2
3const freshFruits = fruits.map(() => `очень свежие!`);
4console.log(freshFruits);
5// ['очень свежие!', 'очень свежие!', 'очень свежие!']

Некоторые разработчики вместо пустых скобок используют переменную _, что имеет по большей мере эстетическое значение.

1const freshFruits = fruits.map((_) => `очень свежие!`);

Лично я предпочитаю использовать () => вместо(_) =>, когда в функцию не требуется передовать аргументы.

Все стрелочные функции - безымянные

Для начала, приведу пример функции с указанием названия:

1function getFreshFruits(fruit) {
2 console.log(`Купим свежие ${fruit}`);
3}
4getFreshFruits('бананы');

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

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

С другой стороны, стрелочную функцию можно присвоить переменной. В этом примере мы объявляем стрелочную функцию и присваиваем ее переменной, используя function expression:

1const getFfreshFruit = (fruit) => {
2 console.log(`Купим свежие ${fruit}`);
3};
4getFfreshFruit('бананы');

Если, у вас нет жестких требований к более детальному отображению ошибок (с указанием названия функции), смело используйте стрелочные функции!

Значение this в стрелочных функциях

Внутри обычной функции значение this зависит от того, как была вызвана функция.

Например, при обычном выполнении функции, значение this - глобальный объект.

1function test() {
2 console.log(this);
3}
4test();
5// Window

Если вы вызываем функцию объекта, то значением this является сам объект.

1const testObject = {
2 myFunction() {
3 console.log(this);
4 },
5};
6testObject.myFunction();
7// testObject

У стрелочных функций отсутствует собственный контекст выполнения, следовательно, значение this в стрелочных функциях всегда наследуется от родительской (внешней) функции.

В этом примере мы получим undefined для каждого числа в массиве numbers:

1const logNumber = {
2 message: 'Номер > ',
3 numbers: [1, 2, 3, 4],
4
5 list() {
6 this.numbers.forEach(function (number) {
7 console.log(this.message, number);
8 });
9 },
10};
11
12logNumber();
13// undefined 1
14// undefined 2
15// undefined 3
16// undefined 4

Значение this, которое мы получаем внутри console.log(this.message, number) определяется обычной функцией. Эта функция не привязана к нашему объекту, поэтому получаем - undefined.

Теоретически, можно использовать метод .bind(), чтобы это исправить:

1const logNumber = {
2 message: 'Номер > ',
3 numbers: [1, 2, 3, 4],
4
5 list() {
6 this.numbers.forEach(
7 function (number) {
8 console.log(this.message, number);
9 }.bind(this)
10 );
11 },
12};
13
14logNumber();
15// Номер > 1
16// Номер > 2
17// Номер > 3
18// Номер > 4

Второй вариант - использовать стрелочную функцию.

1const logNumber = {
2 message: 'Номер > ',
3 numbers: [1, 2, 3, 4],
4
5 list() {
6 // используем стрелочную функцию
7 this.numbers.forEach((number) => {
8 console.log(this.message, number);
9 });
10 },
11};
12
13logNumber();
14// Номер > 1
15// Номер > 2
16// Номер > 3
17// Номер > 4

Значение this внутри обыкновенной функции - зависит от контекста вызова. Значение this в стрелочной функции всегда принимает значение внешней функции!