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


  1. Voiddancer
    29.05.2023 02:44
    +6

    Насчёт this для стрелочных функций тема плохо раскрыта, а это самое важное отличие.


    1. black1277
      29.05.2023 02:44
      +1

      Согласен. Уже 23 год, тема стрелочных ф-й изжевана-пережёвана. Если писать такую статью, то нужно охватить все моменты. Добавлю главное из упущенного:
      лучшей заменой объекта arguments в стрелочных функциях являются остаточные параметры;
      всплытие (hoisting) у обычных ф-й есть всегда, а у стрелочных согласно поведению переменных, в которые были присвоены;
      оператор yield можно использовать в обычных ф-ях, в стрелочных - нет;
      в обычных ф-ях можно привязать новый контекст(call,bind,apply), в стрелочных - нет;


    1. mvv-rus
      29.05.2023 02:44
      +1

      Тема (IMHO) плохо раскрыта, потому что не упомянут тот самый принцип, который заменяет, согласно известному выражению, многие факты — лексическое окружение. У "обычных" функций свое лексическое окружение есть, а у стрелочных — нет. А уж из этого проистекает и отсутствие своего this, и своего arguments, и невозможность выызова в качестве конструктора.


    1. Gaziev_11_rus
      29.05.2023 02:44
      +1

      Поддерживаю!

      Добавлю от себя: тема стрелочных функций хорошо раскрыта тут и тут + есть сразу задачки для закрепления материала. Крайне рекомендую для начинающих.

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

      А так же, если у вас есть проблемы с пониманием, что такое this в javascript, то рекомендую


  1. dopusteam
    29.05.2023 02:44

    то же правило применяется и к скобкам, поскольку они необходимы только в том случае, если необходимо передать более одного аргумента

    А как передать один аргумент без скобок?

    А, речь про запись

    const method = s => console.log(s);

    ?

    Написано, конечно, не особо понятно, тут скорее речь про "принять более одного аргумента", а не "передать"


  1. sergiodev
    29.05.2023 02:44
    +1

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

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