Давайте дружить в Телеграме: рассказываем про новые фичи, общаемся в комментах, прислушиваемся к вашим идеям Подписаться

Стрелочные функции в JavaScript

Илья Ушаков
Илья Ушаков
Технический писатель
15 мая 2023 г.
1109
8 минут чтения
Средний рейтинг статьи: 5

После выпуска шестого стандарта ES6 в 2015 году программисты получили ряд новых возможностей и функций в JavaScript. Стрелочные функции, способы объявления переменных let и const, промисы и множество других фундаментальных изменений были доработаны и добавлены в язык с выходом нового стандарта. Из всего списка изменений мы заострим внимание на стрелочных функциях.

Вкратце, стрелочные функции в JavaScript — это новый метод объявления функциональных выражений, который гораздо компактнее и удобнее своего предшественника. Если вы знакомы с лямбда-функциями в Python, то обязательно найдете между ними сходства.

В данной статье мы рассмотрим стрелочные функции и их синтаксис, приведем примеры их использования, а также изучим все тонкости их применения в коде.

Функции

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

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

Синтаксис объявления стандартной функции (function declaration statement) выглядит следующим образом:

function имя_функции(набор_параметров) {
набор_команд;
}

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

Пример обычной функции:

console.log(multiplication(2,5));

function multiplication (x, y) {
return x * y;
}

Результат работы программы продемонстрирован на картинке ниже.

Image6

Функциональное выражение (function definition expression) — это еще один метод объявления функции, в котором она присваивается переменной или константе. Впоследствии ее можно передать аргументом другой функции или использовать в качестве возвращаемого значения.

Синтаксис объявления функционального выражения представлен ниже:

var имя_переменной = function имя_функции (набор_параметров) {
набор_команд;
}

Параметр имя_функции необязателен. При его отсутствии функция будет считаться анонимной.

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

Пример функционального выражения:

const multiplication = function (x, y) {
 return x * y;
}

console.log(multiplication(2,5));

Результат работы написанного выше кода показан на картинке ниже.

Image5

Основы стрелочных функций

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

Стрелочные функции (arrow function expression) — это те же функциональные выражения, но анонимные и с некоторыми особенностями синтаксиса. Ниже представим список их главных особенностей:

  • Краткий и понятный синтаксис

Синтаксис стрелочных функций в JavaScript интуитивно понятный и краткий. Его базовая версия представлена ниже:

(набор_параметров) => {
набор_команд;
}

Как мы видим, главное отличие стрелочных функций от обычных в JS в отсутствии ключевого слова function и добавлении символов => после списка аргументов в скобках.

Например:

const multiplication = (x, y) => x * y;

console.log(multiplication(2,5));

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

Результат выполнения кода представлен на картинке ниже.

Image3

  • Ключевое слово this

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

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

function Animal() {
    this.group = 'Млекопитающие',
    this.name = 'Слон',
    this.Animal1 = function () {
        console.log('Работа обычной функции:')
        console.log(this.group);

        function exampleFunction1() {
            console.log(this.name);
        }
        exampleFunction1();
    }
    this.Animal2 = function () {
        console.log('Работа стрелочной функции:')
        console.log(this.group);

        let exampleFunction2 = () => console.log(this.name);
        exampleFunction2();
    }
}

let x = new Animal();
x.Animal1();
let y = new Animal();
y.Animal2();

В данном примере this.group доступна как внутри this.Animal1, так и внутри  this.Animal2, так как это два метода одного объекта. Однако внутри этих методов this.name в первом случае возвращает неопределенное значение и мы видим пустоту, так как у данной функции есть собственный контекст (в данном случае — window). Во втором же случае он ссылается на родительскую область видимости и возвращает this.name = 'Слон'. Так мы видим наглядную работу this в обычных и стрелочных функциях.

Результат работы программы представлен на картинке ниже.

Image7

  • Конструкторы

Стрелочные функции не могут использоваться в качестве конструкторов, а также не могут иметь собственных свойств и методов, так как у них отсутствует свойство prototype, которое существует у обычных функций. При их вызове с оператором new система выдаст подобную ошибку.

Image4

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

(firstName, lastName) => {firstName: firstName, lastName: lastName};

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

(firstName, lastName) => ({firstName: firstName, lastName: lastName});

Примеры использования

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

const example_numbers = [1, 2, 3, 4, 5];

const doubling = example_numbers.map(number => number * 2);

console.log(doubling);

Результат работы кода, который удваивает элементы массива, представлен на картинке ниже.

Image8

Так же, как с фигурными скобками, мы можем опустить и круглые скобки, если указан всего один параметр, как в примере выше.

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

const example_numbers = [1, 2, 3, 4, 5];

const sum = example_numbers.reduce((total, number) => total + number, 0);

console.log(sum);

В результате мы получим следующее:

Image9

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

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

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

Приведем пример:

let animal = {
    group: 'Земноводные',
    name: 'Озёрная лягушка',
    infoAnimal: () => {        
console.log('Группа животных -',this.group);
console.log('Название животного -',this.name);
    },
}

animal.infoAnimal(); 

В примере у нас есть метод infoAnimal, который отвечает за вывод информации об объекте, когда мы его вызываем с помощью animal.infoAnimal(). В данном случае его лексическое окружение — это window. А следовательно она никак не связана с свойствами объекта group и name. Результат работы программы представлен на картинке ниже.

Image2

Теперь перепишем код, используя обычную функцию, и посмотрим на результат:

let animal = {
    group: 'Земноводные',
    name: 'Озёрная лягушка',
    infoAnimal: function () {        
            console.log('Группа животных -',this.group);
    console.log('Название животного -',this.name);
    },
}

animal.infoAnimal(); 

Как видно по картинке ниже, метод успешно работает.

Image1

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

Что запомнить

  • Стрелочные функции (arrow function expression) — это те же функциональные выражения, но анонимные и с некоторыми особенностями синтаксиса.
  • Базовый синтаксис выглядит следующим образом:
(набор_параметров) => {
набор_команд;
}
  • Во время использования рассматриваемых в статье функций допускается выполнять удаление круглых скобок вокруг параметра, если он один. А также допускается использовать неявный возврат, который подразумевает удаление фигурных скобок и ключевого слова return, если в функции реализована всего одна операция.
  • Работают стрелочные функции только в той области видимости, в который были объявлены, а также не имеют своего функционального контекста выполнения. Это подразумевает, что такие сущности, как this или argument, наследуются исключительно у родительских функций.
  • При работе с методами объекта, динамическим контекстом или конструкторами нужно использовать обычные функции, а не стрелочные.

Зарегистрируйтесь и начните пользоваться
сервисами Timeweb Cloud прямо сейчас

15 лет опыта
Сосредоточьтесь на своей работе: об остальном позаботимся мы
165 000 клиентов
Нам доверяют частные лица и компании, от небольших фирм до корпораций
Поддержка 24/7
100+ специалистов поддержки, готовых помочь в чате, тикете и по телефону