> For the complete documentation index, see [llms.txt](https://strctr.gitbook.io/programming/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://strctr.gitbook.io/programming/01-languages/javascript/01-language/c-functions/c1-functions/03.i-arrow-functions-es6.md).

# 03.i Arrow functions (=>)

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

* Более компактный синтаксис
* Не имеют собственного контекста вызова
* Весь контекст определяется по правилам лексической области видимости на основе родительских контекстов.
  * `arguments`
  * `super`
  * `this`
  * `new.target`
* Их нельзя использовать в качестве конструктора

## Syntax

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

```javascript
([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-функции, чье тело представляет собой одно выражение могут не содержать фигурных скобок:

```javascript
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`.

```javascript
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` миллисекунд:

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

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

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