Главная » Статьи » Начало работы с современным JavaScript – стрелочные функции

Начало работы с современным JavaScript – стрелочные функции

От автора: одна из самых популярных новых функций в ECMAScript 2015 – стрелочные функции. Это так благодаря новому более чистому синтаксису или совместному использованию их с родительской областью? Возможно по обеим причинам. Давайте разберемся с ними подробнее.

Первым фактором, повлиявшим на внедрение стрелочных функций, был более короткий синтаксис функции. Синтаксис может немного отличаться в зависимости от функции. Рассмотрим несколько вариантов! Вот функция, написанная в синтаксисе ES5:

var sum = function(a, b) { return a + b;
} sum(1, 2) // -> 3

А вот то же самое в виде стрелочной функции:

const sum = (a, b) => a + b; sum(1, 2) // -> 3

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

const printSum = (a, b) => { const result = a + b; console.log('Answer: ' + result); return result;
} const sum = printSum(1, 2); // -> Answer: 3

Скобки необязательны, если присутствует только один параметр:

const square = n => n * n; square(3); // -> 9

Стрелочные функции иногда называют функциями жирных стрелок из-за того, что маркер => похож на жирную стрелку.

Обычный вариант применения стрелочных функций — использование методов массива. Здесь мы создаем новый массив с возрастом игроков, отображая его через массив player:

const players = [ { name:'Michael', age:44}, { name:'Karl', age:33}, { name:'Lisa', age:37}
]; const ages = players.map(player => player.age); // [44, 33, 37]

Здесь это действительно полезно!

This

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

В глобальной области значением this всегда является объект window.

Обычные функции

Функции имеют свой собственный контекст выполнения, а вместе с ним и свой собственный this. Понять эти концепции непросто, но они важны.

Надеемся, что пример кода сделает это более понятным. Чтобы показать разницу, мы используем встроенную функцию JavaScript setTimeout, которая вызывает функцию после задержки, заданной в миллисекундах.

// ES5
function Age() { this.age = 42; setTimeout(function() { console.log(this.age); // -> undefined }, 1000);
} var a = new Age();

Если мы запустим этот код, то получим в консоли undefined, потому что функция внутри setTimeout имеет свой собственный контекст выполнения. Таким образом, мы не получим this.age в функции Age, но это будет в одной из внутренних функций, где мы делаем вызов. И это не придало значения age.

Чтобы получить доступ к контексту родительской функции, разработчики часто переназначают внешнюю функцию this на переменную, обычно называемую that или self.

// ES5
function Age() { var that = this; that.age = 42; setTimeout(function() { console.log(that.age); // -> 42 }, 1000);
} var a = new Age();

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

Другой вариант — использовать function{}.bind(this).

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

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

// ES6
function Age() { this.age = 42; setTimeout(() => { console.log(this.age); // -> 42 }, 1000);
} const a = new Age();

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

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

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

Методы

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

const blog = { likes: 0, like: () => { this.likes++; }
}

Казалось бы, каждый раз, когда мы вызываем атрибут blog.like(), blog.like увеличивается на единицу. Однако, к сожалению, ценность like останется нулевой.

На этот раз родительской областью является объект window, а не объект blog блога. Таким образом, при вызове метода like() будет предпринята попытка увеличить свойство объекта окна like.

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

const blog = { likes: 0, like: function() { this.likes++; }
}

Еще одна новая функция в ES6 — это сокращенный синтаксис метода:

const blog = { likes: 0, like() { this.likes++; }
}

Обратите внимание, что мы можем опустить ключевое слово function и двоеточие.

Конструктор

Стрелочную функцию нельзя использовать в качестве конструктора. При использовании с new:

const PrintDouble = (x) => console.log(2 * x); new PrintDouble(2);
// -> TypeError: PrintDouble is not a constructor

Вместо этого мы можем использовать выражение функции:

const PrintDouble = function(x) { console.log(2 * x);
}; new PrintDouble (2); // -> 4

Заключение

Стрелочные функции — отличное новое дополнение ES6, которое предлагает нам синтаксически компактную альтернативу обычной функции. Стрелочная функция не имеет собственного this. Используется значение this, охватывающее эту лексическую область. Стрелочные функции плохо подходят в качестве методов и не могут использоваться в качестве конструкторов.

Автор: Michael Karén

Источник: indepth.dev

Редакция: Команда webformyself.