Сравнение стрелочных функций и обычных функций в JavaScript

Стрелочные функции — это фантастическая функция, представленная в ECMAScript 6 (ES6). ES6 был опубликован в 2015 году. Я начал свою карьеру разработчика в 2017 году. Поэтому, когда я написал свою первую программу на JavaScript, стрелочные функции были на сцене.
По моему личному мнению, я предпочитаю использовать стрелочные функции при любой возможности. время я могу. Причина в том, что коды со стрелочными функциями четкие и легко читаемые, когда мы сравниваем коды с обычными функциями, а я чувствую себя комфортно со стрелочными функциями.

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

«В чем разница между стрелочными функциями и обычными функциями?» – часто задаваемый вопрос на собеседованиях по JavaScript. Так что не пропустите этот контент, если ваша цель — освоить JavaScript.

Давайте начнем с основных вещей, а затем обсудим более сложные вопросы по этой теме.

Функции, которые мы определяем с помощью ключевого слова function, называются обычными функциями. Мы можем определить регулярные функции двумя способами:

  1. Объявления функций
  2. Функциональные выражения
// Function declaration
function sayHello(name) {
   return `Hello ${name}`
}
// Function expression
const sayHello = function(name) {
   return `Hello ${name}`
}

Мы можем определить вышеуказанную регулярную функцию как стрелочную функцию следующим образом:

const sayHello = (name) => `Hello ${name}`;

Рекомендации, которым следует следовать при определении функции стрелки.

  • Когда функция принимает только один параметр, круглые скобки перед символом => не обязательны. Но функция принимает больше, чем параметры; скобки обязательны.
  • Не нужно использовать фигурные скобки после символа =>, если тело функции имеет однострочное выражение. Если это не так, фигурные скобки обязательны.

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

const add = (a, b) => a + b;
const sayHello = name => `Hello ${name}`;
const someFunction = (x, y, z) => {
  // do some stuff
  ...
  return z;
}

Основные вещи сделаны. Теперь давайте перейдем к нашей теме.

Разное поведение с ключевым словом this

В обычных функциях ключевое слово this является динамическим и зависит от контекста выполнения.

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

function myFunction() {
  console.log(this); // global object
}
myFunction();

Во время простого вызова, как в приведенном выше фрагменте кода, this равно объекту global. Это работает так же, если мы преобразуем myFunction в функцию стрелки.

const myFunction = () => {
  console.log(this); // global object
}
myFunction();

Если мы делаем вызов конструктора, используя new myFunction(),
в обычных функциях, this равняется только что созданному экземпляру myFunction {}, но если мы делаем то же самое со стрелкой функции, выдает ошибку TypeError: myFunction is not a constructor.

function myFunction() {
  console.log(this);   // myFunction {}
}
// constructor invocation
new myFunction();
const myFunction = () => {
  console.log(this);   // TypeError: myFunction is not a constructor
}
// constructor invocation
new myFunction();

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

const dog = {
  name: 'Lassie',
  bark: function () {
    console.log(this);   // { name: 'Lassie', bark: ƒ }
  }
}
// Normal function method invocation
dog.bark();
const dog = {
  name: 'Lassie',
  bark: () => {
    console.log(this);  // global object
  },
}
// Arrow function method invocation
dog.bark();

Во время вызова метода, как и в приведенном выше фрагменте кода, в обычных функциях this соответствует объекту-владельцу, а в стрелочных функциях this относится к лексической области видимости внешней функции. . В приведенном выше фрагменте кода this соответствует объекту global, поскольку объект dog объявлен на корневом уровне скрипта.

const dogObject = { name: 'Lassie' };
// Normal Function
function createDog() {
  console.log(this); // { name: 'Lassie' }
}
createDog.call(dogObject);
createDog.apply(dogObject);
// Arrow Function
const createDog = () => {
console.log(this); // global object
};
createDog.call(dogObject);
createDog.apply(dogObject);

Во время косвенных вызовов с использованием function.call(context) или function.apply(context) в обычных функциях this равно первому аргументу; в приведенном выше фрагменте кода это dogObject. В стрелочных функциях значение this не изменяется, и, тем не менее, this разрешается лексически. В приведенном выше фрагменте кода this соответствует объекту global, поскольку функция createDog объявлена ​​на корневом уровне скрипта.

Привязка аргумента

Обычные функции имеют привязку аргументов. Вот почему мы можем получить доступ к тем, кто использует ключевое слово arguments внутри тела функции. Но стрелочные функции не имеют привязки аргументов. Если мы попытаемся получить доступ к тем, кто использует ключевое слово arguments, это выдаст ошибку: ReferenceError: arguments is not defined.
См. пример ниже.

function x() {
  console.log(arguments);
  // [1, 2, 3, callee: ƒ, Symbol(Symbol.iterator): ƒ]
}
x(1, 2, 3);
const y = () => {
  console.log(arguments); 
  // ReferenceError: arguments is not defined
}
y(1, 2, 3);

Но мы можем получить доступ к аргументам внутри стрелочной функции, используя оператор расширения следующим образом:

const y = (...n) => {
  console.log(n);
}
y(1, 2, 3);

Где не следует использовать стрелочные функции

  • Чтобы определить функции внутри объектов.
const person = {
  age: 30,
  sayAge: () => {
    console.log(`I am ${this.age} years old.`);
    // I am undefined years old.
  },
}
person.sayAge();

Теперь вы должны знать, что возраст указан undefined 😎.

  • Как конструктор
const Employee = () => {};
const employee = new Employee(); 
// TypeError: Employee is not a constructor

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

Знаете ли вы, что такое замыкание?
Нет? Тогда читайте мою предыдущую статью JS Closure.
Да? Еще читал. Вы обязательно узнаете что-то новое.

Спасибо за чтение.😍

Надеюсь, вы узнаете что-то новое, прочитав эту статью. Пожалуйста, следуйте за мной, чтобы читать статьи такого типа в будущем. Ваше здоровье!

Дополнительные материалы на PlainEnglish.io. Подпишитесь на нашу бесплатную еженедельную рассылку новостей. Подпишитесь на нас в Twitter и LinkedIn. Посетите наш Community Discord и присоединитесь к нашему Коллективу талантов.