03.i Arrow functions (=>)

Arrow-функции - это новая разновидность функций в JS:

  • Более компактный синтаксис

  • Не имеют собственного контекста вызова

  • Весь контекст определяется по правилам лексической области видимости на основе родительских контекстов.

    • arguments

    • super

    • this

    • new.target

  • Их нельзя использовать в качестве конструктора

Syntax

Новый синтаксис для задания функций через «стрелку» =>.

([param] [, param]) => {
   statements
}

param => expression

    () => { ... } // no parameter
     x => { ... } // one parameter, an identifier
(x, y) => { ... } // several parameters


x => { return x * x }  // block
x => x * x  // expression, equivalent to previous line

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

const sorted = arr.sort((a, b) => a - b);
const inc = x => x + 1;
const sum = (a, b) => a + b;
const getTime = () => `${new Date().getHours()} : ${new Date().getMinutes()}`; // empty parentless
const wrap = a => ({ a });

Если единственным выражением в теле функции является литерал объекта, то он должен оборачиваться в обычные скобки, что бы подчеркнуть, что это выражение - () => ({...}). Как только тело функции оборачивается в {…}, то для неё начинают действовать те же правила, что и для обычных функций:

Execution Context

Функции-стрелки не имеют ни своего this, ни своего arguments: внутри функций-стрелок — тот же this, что и снаружи. Это очень удобно в обработчиках событий и callback.

Отсутствие у функции-стрелки «своего this влечёт за собой естественное ограничение: такие функции нельзя использовать в качестве конструктора, то есть нельзя вызывать через new.

const group = {
  title: "Наш курс",
  students: ["Вася", "Петя", "Даша"],

  showList() {
    this.students.forEach(student => alert(`${this.title}: ${student}`));
  }
};

group.showList();
// Наш курс: Вася
// Наш курс: Петя
// Наш курс: Даша

Есть тонкое различие между функцией стрелкой => и обычной функцией, у который вызван .bind(this):

  • Вызовом .bind(this) мы передаём текущий this, привязывая его к функции.

  • При => привязки не происходит, так как функция стрелка вообще не имеет контекста this. Поиск this в ней осуществляется по лексическим областям видимости также, как и поиск обычной переменной, то есть, выше в замыкании.

В качестве arguments используются аргументы внешней “обычной” функции. Сохранение внешнего this и arguments удобно использовать для последующей передачи вызовов и создания декораторов. Например, декоратор defer(f, ms) ниже получает функцию f и возвращает обёртку вокруг неё, откладывающую вызов на ms миллисекунд:

function defer(f, ms) {
  return function() {
    setTimeout(() => f.apply(this, arguments), ms);
  };
}

function sayHi(who) {
  alert(`Привет, ${who}!`);
}

let sayHiDeferred = defer(sayHi, 2000);
sayHiDeferred("Вася"); // Привет, Вася! через 2 секунды

Last updated