[Перевод] Разница между традиционными функциями и стрелочными функциями в JavaScript
Не заблуждайтесь, способы объявления функций в 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});
}
sayMyNane('Ernane'); // => My name is Ernane.
Помня, что в случае со стрелочными функциями фигурные скобки необходимы только в том случае, если присутствует выражение, то же правило применяется и к скобкам, поскольку они необходимы только в том случае, если необходимо передать более одного аргумента. Таким образом, мы могли бы уменьшить его еще больше и записать приведенный выше пример следующим образом:
const sayMyName = name => console.log(My name is ${name};
sayMyNane('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(){
console.log(My name is ${name});
}
new sayMyName('Ernane'); // => Ernane
Что касается стрелочных функций :
const sayMyName = () => 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.
Таким образом, всегда полезно уделять пристальное внимание использованию стрелочных функций вместо традиционных функций. Хотя их синтаксис очень приятен, в них есть некоторые моменты, к которым мы должны быть внимательны, чтобы не пропустить их.
В любом случае рекомендуется дальнейшее изучение этого вопроса. Как всегда, я оставлю ниже несколько рекомендательных ссылок для углубления темы.
Надеюсь, вам понравился этот пост и он помог вам найти то, что вы искали!