--- title: Стрілкові функції slug: Web/JavaScript/Reference/Functions/Arrow_functions translation_of: Web/JavaScript/Reference/Functions/Arrow_functions original_slug: Web/JavaScript/Reference/Functions/Стрілкові_функції ---
{{jsSidebar("Functions")}}

Вирази стрілкових функцій мають більш короткий синтаксис, аніж функціональні вирази і не мають свого власного this, arguments, super, і new.target. Вони не можуть бути використані як конструктор і завжди анонімні.

Синтаксис

Basic Syntax

(параметр1,параметр2, …, параметрN) => { оператори }
(параметр1, параметр2, …, параметрN) => вираз
// еквівалентно до запису: (параметр1,параметр2, …, параметрN) => { return вираз; }

// Якщо у функції тільки один параметр, то дужки не обов'язкові:
(параметр) => { оператори }
параметр => { оператори }
параметр => вираз


// Список параметрів для функції без параметрів повинен бути записаний у парі фігурних дужок.
() => { оператори }

Advanced Syntax

// Візьміть тіло функції у дужки, якщо вона повертає об'єкт
params => ({foo: bar})

// Залишкові параметри та параметри за замовчуванням підтримуються як і в звичайних функціях
(параметр1, параметр2, ...залишкові параметри) => { оператори }
(параметр1 = значення_за_замовчуванням, параметр2, …, параметрN = значення_за_замовчуваннямN) => { оператори }

// Деструктиризація в списку параметрів також підтримується:
let f = ([a, b] = [1, 2], {x: c} = {x: a + b}) => a + b + c;
f();
// 6

Опис

Див. також "ES6 In Depth: Arrow functions" on hacks.mozilla.org.

Появу стрілкових функцій зумовили два фактори: можливість більш короткого запису і випадки, коли сутність this не обов'язкова.

Коротший запис

var materials = [
  'Hydrogen',
  'Helium',
  'Lithium',
  'Beryllium'
];

materials.map(function(material) {
  return material.length;
}); // [8, 6, 7, 9]

materials.map((material) => {
  return material.length;
}); // [8, 6, 7, 9]

materials.map(material => material.length); // [8, 6, 7, 9]

Спільний this

До появи стрілкових функцій кожна нова функція мала власне значення this :

Це все було далеким від ідеалів об'єктно-орієнтованого програмування.

function Person() {
  // The Person() constructor defines `this` as an instance of itself.
  this.age = 0;

  setInterval(function growUp() {
    // In non-strict mode, the growUp() function defines `this`
    // as the global object, which is different from the `this`
    // defined by the Person() constructor.
    this.age++;
  }, 1000);
}

var p = new Person();

В ECMAScript 3/5 ця проблема вирішувалась шляхом присвоєння значення this змінній, оголошеній всередині функції.

function Person() {
  var that = this;
  that.age = 0;

  setInterval(function growUp() {
    // The callback refers to the `that` variable of which
    // the value is the expected object.
    that.age++;
  }, 1000);
}

Або можна створити bound function (прив'язану функцію), в яку передати значення this для функції (функція growUp() в прикладі вище).

Стрілкова функція не має власного контексту this, а використовує this з контексту вище. Тому в коді, наведеному нижче, this для функції setInterval має таке ж значення, як і this зовнішньої функції:

function Person(){
  this.age = 0;

  setInterval(() => {
    this.age++; // |this| properly refers to the person object
  }, 1000);
}

var p = new Person();

Relation with strict mode

Given that this comes from the surrounding lexical context, strict mode rules with regard to this are ignored.

var f = () => { 'use strict'; return this; };
f() === window; // or the global object

All other strict mode rules apply normally.

Invoked through call or apply

Since arrow functions do not have their own this, the methods call() or apply() can only pass in parameters. thisArg is ignored.

var adder = {
  base: 1,

  add: function(a) {
    var f = v => v + this.base;
    return f(a);
  },

  addThruCall: function(a) {
    var f = v => v + this.base;
    var b = {
      base: 2
    };

    return f.call(b, a);
  }
};

console.log(adder.add(1));         // This would log to 2
console.log(adder.addThruCall(1)); // This would log to 2 still

No binding of arguments

Arrow functions do not have their own arguments object. Thus, in this example, arguments is simply a reference to the arguments of the enclosing scope:

var arguments = [1, 2, 3];
var arr = () => arguments[0];

arr(); // 1

function foo(n) {
  var f = () => arguments[0] + n; // foo's implicit arguments binding. arguments[0] is n
  return f(10);
}

foo(1); // 2

In most cases, using rest parameters is a good alternative to using an arguments object.

function foo(n) {
  var f = (...args) => args[0] + n;
  return f(10);
}

foo(1); // 11

Arrow functions used as methods

As stated previously, arrow function expressions are best suited for non-method functions. Let's see what happens when we try to use them as methods:

'use strict';
var obj = {
  i: 10,
  b: () => console.log(this.i, this),
  c: function() {
    console.log(this.i, this);
  }
}
obj.b(); // prints undefined, Window {...} (or the global object)
obj.c(); // prints 10, Object {...}

Arrow functions do not have their own this. Another example involving {{jsxref("Object.defineProperty()")}}:

'use strict';
var obj = {
  a: 10
};

Object.defineProperty(obj, 'b', {
  get: () => {
    console.log(this.a, typeof this.a, this);
    return this.a + 10; // represents global object 'Window', therefore 'this.a' returns 'undefined'
  }
});

Use of the new operator

Arrow functions cannot be used as constructors and will throw an error when used with new.

var Foo = () => {};
var foo = new Foo(); // TypeError: Foo is not a constructor

Use of prototype property

Arrow functions do not have a prototype property.

var Foo = () => {};
console.log(Foo.prototype); // undefined

Use of the yield keyword

The yield keyword may not be used in an arrow function's body (except when permitted within functions further nested within it). As a consequence, arrow functions cannot be used as generators.

Тіло функції

Arrow functions can have either a "concise body" or the usual "block body".

In a concise body, only an expression is specified, which becomes the explicit return value. In a block body, you must use an explicit return statement.

var func = x => x * x;
// concise body syntax, implied "return"

var func = (x, y) => { return x + y; };
// with block body, explicit "return" needed

Повернення літерала об'єкта

Keep in mind that returning object literals using the concise body syntax params => {object:literal} will not work as expected.

var func = () => { foo: 1 };
// Calling func() returns undefined!

var func = () => { foo: function() {} };
// SyntaxError: function statement requires a name

This is because the code inside braces ({}) is parsed as a sequence of statements (i.e. foo is treated like a label, not a key in an object literal).

Remember to wrap the object literal in parentheses.

var func = () => ({foo: 1});

Розрив рядка

An arrow function cannot contain a line break between its parameters and its arrow.

var func = ()
           => 1;
// SyntaxError: expected expression, got '=>'

Порядок розбору

Although the arrow in an arrow function is not an operator, arrow functions have special parsing rules that interact differently with operator precedence compared to regular functions.

let callback;

callback = callback || function() {}; // ok

callback = callback || () => {};
// SyntaxError: invalid arrow-function arguments

callback = callback || (() => {});    // ok

Ще приклади

// An empty arrow function returns undefined
let empty = () => {};

(() => 'foobar')();
// Returns "foobar"
// (this is an Immediately Invoked Function Expression
// see 'IIFE' in glossary)

var simple = a => a > 15 ? 15 : a;
simple(16); // 15
simple(10); // 10

let max = (a, b) => a > b ? a : b;

// Easy array filtering, mapping, ...

var arr = [5, 6, 13, 0, 1, 18, 23];

var sum = arr.reduce((a, b) => a + b);
// 66

var even = arr.filter(v => v % 2 == 0);
// [6, 0, 18]

var double = arr.map(v => v * 2);
// [10, 12, 26, 0, 2, 36, 46]

// More concise promise chains
promise.then(a => {
  // ...
}).then(b => {
  // ...
});

// Parameterless arrow functions that are visually easier to parse
setTimeout( () => {
  console.log('I happen sooner');
  setTimeout( () => {
    // deeper code
    console.log('I happen later');
  }, 1);
}, 1);

Специфікації

Специфікація Статус Коментар
{{SpecName('ES2015', '#sec-arrow-function-definitions', 'Arrow Function Definitions')}} {{Spec2('ES2015')}} Початкова виознака.
{{SpecName('ESDraft', '#sec-arrow-function-definitions', 'Arrow Function Definitions')}} {{Spec2('ESDraft')}}

Підтримка веб-переглядачами

{{Compat("javascript.functions.arrow_functions")}}

Див. також