Не заблуждайтесь, способы объявления функций в Javascript отличаются не только компактностью и элегантным синтаксисом.
Стрелочные функции — это относительно новая функция, реализованная в ES6 ( ECMAScript 6 ), которая, на наш взгляд, является просто более кратким и элегантным синтаксисом для объявления функциональных выражений в JavaScript. Хотя традиционные функции и функции стрелок работают схожим образом, мы должны остерегаться некоторых различий, которые могут быть незаметны.
Синтаксис
Разница в синтаксисе между двумя моделями общеизвестна, поскольку в стрелочной функции становится возможным значительно сократить количество строк, присутствующих в объявлении функции, особенно если это уже простая функция. См. примеры:
Представьте себе функцию, которая берет имя пользователя и выводит его в консоль. Традиционным способом мы могли бы объявить это так:
function sayMyNane(name){
console.log(`My name is ${name}!`);
}
sayMyNane('Ernane'); // => My name is Ernane.
Со стрелочными функциями из ES6 мы могли бы сделать это следующим образом:
const sayMyName = (name) => {
console.log(`My name is ${name}`);
};
sayMyName("Ernane"); // => My name is Ernane.
Помня, что в случае со стрелочными функциями фигурные скобки необходимы только в том случае, если присутствует выражение, то же правило применяется и к скобкам, поскольку они необходимы только в том случае, если необходимо передать более одного аргумента. Таким образом, мы могли бы уменьшить его еще больше и записать приведенный выше пример следующим образом:
const sayMyName = (name) => console.log(`My name is ${name}`);
sayMyName("Ernane"); // => My name is Ernane.
Просто, не так ли? Таким образом, мы можем увидеть, как стрелочная функция может облегчить объявление определенной функции из-за своего синтаксиса и при этом вернуть тот же результат, что и обычное объявление.
Использование ключевого слова «this»
В отличие от традиционного объявления, стрелочные функции не имеют собственного элемента this , поскольку значение this внутри стрелочной функции остается неизменным на протяжении всего жизненного цикла функции и всегда привязано к значению this в ближайшей традиционной родительской функции.
Это стало немного странно? Позвольте мне попытаться упростить с примером:
Возвращаясь к примеру, использованному в предыдущем разделе, представьте, что у нас есть объект person
, имя которого определено как один из его атрибутов, и функция, которая выводит имя этого конкретного человека в консоль. В зависимости от типа используемой функции она не сможет правильно получить доступ к родительскому объекту, имеющему запрошенный атрибут имени , и, следовательно, ее возврат будет undefined
.
let person = {
name: "Ernane Ferreira",
sayMyName: () => console.log(`My name is ${this.name}.`),
};
person.sayMyName(); // => My name is .
В случае объявления функции в традиционной модели это будет работать как положено и мы правильно получим искомый атрибут.
let person = {
name: "Ernane Ferreira",
sayMyName: function () {
console.log(`My name is ${this.name}.`);
},
};
person.sayMyName(); // => My name is Ernane Ferreira.
Доступ к аргументам
Объект arguments — это локальная переменная, доступная внутри всех функций, и это то, что делает ссылку возможными аргументами функции внутри нее, используя объект arguments. Однако стрелочные функции не имеют ссылки на arguments
объект:
const showArguments = () => console.log(arguments);
showArguments(1, 2, 3) // => ReferenceError: arguments is not defined.
В случае обычной функции мы можем легко получить доступ к списку аргументов, переданных в качестве параметра при вызове функции:
function showArguments(){
console.log(arguments);
}
showArguments(1, 2, 3) // => Arguments(3) [1, 2, 3]
Использование оператора new
Оператор new позволяет создавать экземпляры определяемого пользователем типа объекта или одного из определяемых пользователем типов. внутренних объектов, которые имеют функцию конструктора . Традиционные функции являются конструируемыми и могут быть вызваны с помощью оператораnew
. С другой стороны, стрелочные функции являются вызываемыми, а не конструируемыми, то есть эти функции никогда не могут использоваться в качестве функций-конструкторов и никогда не могут вызываться с помощью оператора new
.
Поэтому для такого типа выполнения в традиционных функциях мы получаем следующий результат выполнения:
function sayMyName(name) {
console.log(`My name is ${name}`);
}
new sayMyName("Ernane"); // => Ernane
Что касается стрелочных функций :
const sayMyName = (name) => console.log(`My name is ${name}`);
new sayMyName("Ernane"); // => Uncaught TypeError: sayMyName is not a constructor
Параметры с дублирующимся именем
Стрелочные функции не допускают дублирования имен параметров, но традиционные функции допускают зависимость от применения или неприменения строгого режима ( Strict Mode ) в реализации кода. Например, приведенный ниже JavaScript полностью действителен:
function addTwoNumbers(x, x){
console.log(x+x);
}
addTwoNumbers(1,1); // => 2
Однако тот же код с примененным строгим режимом больше недействителен:
"use strict";
function addTwoNumbers(x, x) {
console.log(x + x);
}
// => Uncaught SyntaxError: Duplicate parameter name not allowed in this context
При использовании стрелочных функций это происходит независимо от того, применяется ли строгий режим. В обоих случаях выполнение недействительно:
const addTwoNumbers = (x, x) => console.log(x+x);
// => SyntaxError: Uncaught SyntaxError: Duplicate parameter name not allowed in this context.
Таким образом, всегда полезно уделять пристальное внимание использованию стрелочных функций вместо традиционных функций. Хотя их синтаксис очень приятен, в них есть некоторые моменты, к которым мы должны быть внимательны, чтобы не пропустить их.
В любом случае рекомендуется дальнейшее изучение этого вопроса. Как всегда, я оставлю ниже несколько рекомендательных ссылок для углубления темы.
Надеюсь, вам понравился этот пост и он помог вам найти то, что вы искали!
Ссылки
Комментарии (6)
dopusteam
29.05.2023 02:44то же правило применяется и к скобкам, поскольку они необходимы только в том случае, если необходимо передать более одного аргумента
А как передать один аргумент без скобок?
А, речь про запись
const method = s => console.log(s);
?
Написано, конечно, не особо понятно, тут скорее речь про "принять более одного аргумента", а не "передать"
sergiodev
29.05.2023 02:44+1Помня, что в случае со стрелочными функциями фигурные скобки необходимы только в том случае, если присутствует выражение,
Тут не очень правильно написано. Выражение может присутствовать и без фигурных скобок. Видимо, имелось ввиду, что они НЕ нужны, когда функция целиком состоит из одного выражения, вовращаемого из нее.
Voiddancer
Насчёт this для стрелочных функций тема плохо раскрыта, а это самое важное отличие.
black1277
Согласен. Уже 23 год, тема стрелочных ф-й изжевана-пережёвана. Если писать такую статью, то нужно охватить все моменты. Добавлю главное из упущенного:
лучшей заменой объекта arguments в стрелочных функциях являются остаточные параметры;
всплытие (hoisting) у обычных ф-й есть всегда, а у стрелочных согласно поведению переменных, в которые были присвоены;
оператор yield можно использовать в обычных ф-ях, в стрелочных - нет;
в обычных ф-ях можно привязать новый контекст(call,bind,apply), в стрелочных - нет;
mvv-rus
Тема (IMHO) плохо раскрыта, потому что не упомянут тот самый принцип, который заменяет, согласно известному выражению, многие факты — лексическое окружение. У "обычных" функций свое лексическое окружение есть, а у стрелочных — нет. А уж из этого проистекает и отсутствие своего this, и своего arguments, и невозможность выызова в качестве конструктора.
Gaziev_11_rus
Поддерживаю!
Добавлю от себя: тема стрелочных функций хорошо раскрыта тут и тут + есть сразу задачки для закрепления материала. Крайне рекомендую для начинающих.
Так же в статье не говорится о том, какую проблему решают стрелочных функции, об этом можно узнать тут.
А так же, если у вас есть проблемы с пониманием, что такое this в javascript, то рекомендую