[Перевод] Разница между традиционными функциями и стрелочными функциями в JavaScript

e2b38fc0be3328d0c82d555c2fa74cbb

Не заблуждайтесь, способы объявления функций в 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.

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

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

Надеюсь, вам понравился этот пост и он помог вам найти то, что вы искали!

Ссылки

© Habrahabr.ru