В этой статье мы рассмотрим разницу между стрелочными функциями ES6 и обычными функциями

ES6 (также известный как ES2015) предоставил разработчикам JavaScript возможность использовать то, что называется стрелочными функциями.

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

const sayHi = function(name) {
   return `Hi ${name}`;
}

Мы можем просто написать

const sayHi = (name) => {
    return `Hi ${name}`;
}

Итак, как мы видим выше, стрелочные функции предоставляют нам более короткий синтаксис для написания функций, что является большим преимуществом. Мы можем даже упростить приведенный выше синтаксис стрелочной функции и удалить круглые скобки вокруг аргумента имени, поскольку мы используем только один аргумент (если мы используем более одного, мы должны их сохранить).

const sayHi = name => { 
   return `Hi ${name}`;
}

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

const sayHi = name => `Hi ${name}`;

Внутри обычной функции JavaScript значение this может быть динамическим и зависит от того, как вызывается функция. Существует 4 различных типа типов вызова:

1. Обычный — значение this является глобальным объектом (или не определено, если включен строгий режим)

function sayHi() {
   console.log(this); // this is the global object
}
sayHi();

2. Функция — значение this — это объект, содержащий метод.

const wrapper = {
  sayHi() {
    console.log(this); // this is the wrapper object
  }
};
wrapper.sayHi()

3. Косвенный — значение this — это объект, содержащий метод (например, с использованием call или apply).

const person = { age: 24, name: 'john' };
function sayHi() {
  console.log(this); // this is the person object
}
sayHi.call(person);

4. Конструктор — значение this — это экземпляр, созданный с помощью ключевого слова new.

function sayHi() {
  console.log(this); // this is the instance of sayHi
}
new sayHi();

С другой стороны, стрелочная функция не определяет свой собственный контекст выполнения. Это означает, что не важно, где она выполняется, значение this внутри стрелочной функции всегда будет равно тому же значению, что и внешняя функция. Это также означает, что, в отличие от обычной функции, косвенный вызов стрелочной функции с использованием call или apply не будет работать.

function sayHi(){
 console.log(this.age);
}
sayHi(); // logs undefined, this is the global object
const person = { age : 34 };
sayHi.call(person); // logs 34, call allows binding the this value
const sayHi2 = () => console.log(this.age); 
sayHi2.call(person); // logs undefined, call/apply doesn't work!

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

let person = { 
  arrowHi:() => { 
    console.log(this); 
  },
  regularHi(){ 
    console.log(this); 
  } 
};
person.arrowHi(); // logs the global object
person.regularHi(); // logs person object

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

function Car(brand) {
 this.brand = brand;
}
const reno = new Car(‘Reno’);
console.log(reno instanceof Car); // true
const Car2 = (brand) => {
 this.brand = brand;
};
const reno2 = new Car2(‘Reno’); // error — Uncaught TypeError: Car2 is not a constructor

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

class Person {
  constructor(age) {
    this.age = age;
  }
  sayAge() {
    console.log(“this person age is “ + this.age);
  }
  sayAge2 = () => console.log(“this person age is “ + this.age);
}
const person = new Person(34);
person.sayAge(); // "this person age is 34"
person.sayAge2(); // "this person age is 34"
setTimeout(person.sayAge, 1000); // "this person age is undefined"
// we can actually fix that with bind, but this is an extra overhead
setTimeout(person.sayAge.bind(person), 1000);// "this person age is 34"

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

class Person2 {
  constructor(age) {
    this.age = age;
  }
  sayAge = () => {
    console.log("this person age is " + this.age);
  }
}
const person2 = new Person2(34);
person2.sayAge(); // "this person age is 34"
setTimeout(person2.sayAge, 1000); // "this person age is 34"

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

Вы также можете подписаться на меня, чтобы получать больше таких статей (: