В этой статье мы рассмотрим разницу между стрелочными функциями 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"
Я надеюсь, что эта статья поможет вам понять разницу между стрелочными функциями и обычными функциями и понять, где их разумно использовать. Если вы нашли эту статью полезной, я был бы признателен за аплодисменты ниже (:
Вы также можете подписаться на меня, чтобы получать больше таких статей (: