This translation is incomplete. Please help translate this article from English.

Функционалният израз със стрелка има по-кратък синтаксис, отколкото стандартното дефиниране на функция и няма свой собствен this, arguments, super, или new.target. Тези функции са най-подходящи за не-методни функции и не могат да бъдат използвани като конструктори.

Синтаксис

Основен синтаксис

(param1, param2, …, paramN) => { statements } 
(param1, param2, …, paramN) => expression
// equivalent to: => { return expression; } 

// Parentheses are optional when there's only one parameter name:
(singleParam) => { statements }
singleParam => { statements }

// The parameter list for a function with no parameters should be written with a pair of parentheses.
() => { statements }

Напреднал синтаксис

// Parenthesize the body of function to return an object literal expression:
params => ({foo: bar}) 

// Rest parameters and default parameters are supported
(param1, param2, ...rest) => { statements } 
(param1 = defaultValue1, param2, …, paramN = defaultValueN) => { 
statements } 

// Destructuring within the parameter list is also supported
var 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 elements = [
  'Hydrogen',
  'Helium',
  'Lithium',
  'Beryllium'
];

elements.map(function(element) { 
  return element.length; 
}); // this statement returns the array: [8, 6, 7, 9]

// The regular function above can be written as the arrow function below
elements.map((element) => {
  return element.length;
}); // [8, 6, 7, 9]

// When there is only one parameter, we can remove the surrounding parenthesies:
elements.map(element => {
  return element.length;
}); // [8, 6, 7, 9]

// When the only statement in an arrow function is `return`, we can remove `return` and remove
//  the surrounding curly brackets
elements.map(element => element.length); // [8, 6, 7, 9]

// In this case, because we only need the length property, we can use destructing parameter:
// Notice that the string `"length"` corrosponds to the property we want to get whereas the
//  obviously non-special `lengthFooBArX` is just the name of a variable which can be changed
//  to any valid variable name you want
elements.map(({ "length": lengthFooBArX }) => lengthFooBArX); // [8, 6, 7, 9]

// This destructing parameter assignment can be written as seen below. However, note that there
//   is no specific `"length"` to select which property we want to get. Instead, the literal name
//   itself of the variable `length` is used as the property we want to retrieve from the object.
elements.map(({ length }) => length); // [8, 6, 7, 9]

Без отделна ключова дума this

Допреди функциите със стрелка, всяка нова функция дефинираше своя собствена стойност this  (въз основа на това как се нарича функцията, нов обект в случай на конструктор, недифинарна при извикване на функции в строг режим,основният обект ако функцията се извиква като "object method", etc.). Това се оказа по-малко от идеалното с обектно-ориентирания стил на програмиране.

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 (because it's where growUp() is executed.), 
    // which is different from the `this`
    // defined by the Person() constructor. 
    this.age++;
  }, 1000);
}

var p = new Person();

В ECMAScript 3/5, проблемът с  this беше поправим като присвоим стойността на  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);
}

Като алтернатива, може да бъде създадена свързана функция  така че  this стойността може да бъде предадена на свързаната целева функция (функцията growUp() в примера по-горе).

Функцията със стрелка няма свой собствен this; Стойността  this от използвания лексикален контекст и др. Функциите със стрелки следват нормалните правила на промелнива. Така че, докато търсим за  this,  който не присъства в текущият обхват на функцията, те взимат this от околният обхват. По този начин,в следния код,  this в рамките на функцията, която се предава на setInterval функцията, има същата стойност като на тази в околната лексикална функция:

function Person(){
  this.age = 0;

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

var p = new Person();

Връзка със строг режим

Като се има в предвид , че this идва от околния лексикален контекст, строгите правила за режима по отношение на this се игнорират.

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

Всички други правила за строг режим се прилагат нормално

Извикване чрез повикване или прилагане

Тъй като функциите със стрелка нямат свой собствен this, методите call() или apply() могат само да предават параметри. thisArg се игнорира.

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

Без обвързване на arguments

Функциите със стрелка нямат свой собствен обект от аргументи .Следователно в този пример аргументите са просто препратка към аргументите на заобикалящото ги поле:

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();
}

foo(3); // 6

В повечето случаи, използването на rest parameters(остатъчни параметри) е добра алтернатива от използването на обект с  аргументи.

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

foo(1); // 11

Функции със стрелка използвани като методи

Както бе посочено по-горе, изразите на функциите със стрелките са най-подходящи за функциите, различни от метода. Нека видим какво се случва, когато се опитаме да ги използваме като методи:

'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 {...}

Функциите със стрелка нямат свой собствен this. Друг пример затова е : Object.defineProperty():

'use strict';

var obj = {
  a: 10
};

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

Използване на оператора new

Функциите със стрелка не мога да бъдат използвани като конструктории ще генерират грешка , когато се изпозват с оператора new.

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

Използване на свойството prototype

Функциите със стрелки нямат свойството prototype.

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

Използване на ключовата дума  yield

Ключовата дума yield не може да бъде използвана в тялото на функцията със стрелка ( освен когато е позволено в рамките на функциите, които са вложени в нея ). В резултат на това функциите със стрелки не могат да се използват като генератори.

Тялото на функция

Функциите със стрелка могат да имат или  "сбито тяло" или обичайното "блоково тяло".

В сбитото тяло е посочен само израз, който се превръща в неявна връщана стойност.  В блоково тяло трябва да използвате изрично return декларация за връщане.

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

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

Връщане на литерали на обекти

Имайте в предвид , че връщането на литерали на обекти, използвайки сбит синтаксис params => {object:literal} няма да работи според очакванията.

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

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

Това е защото кодът вътре в скобите ({}) се анализита като оследователност  от изрази (или  fooсе третира като етикет, а не като ключ в буквален обект).

Запомнете, че трябва да поставяте буквалният обект в скоби , както е показано в примера по-долу.

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

Прекъсване на линията

Функцията със стрелка не може да съдържа прекъсната линия между нейните параметри и стрелка.

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

Все пак това може да бъде променено, чрез използване на скоби или поставяне на разделителната линия в аргументите, както е показано в примера по-долу, за да се гарантира, че кодът остава красив и пухкав.

var func = (
  a,
  b,
  c
) => (
  1
); 
// no SyntaxError thrown

 

Parsing order

Въпреки че, стрелката във функцията със стрелка не е оператор, функциите със стрелка имат специални правила, които взаимодействат по различен начин с  оператора за предимство  сравнено с нормалните функции.

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);  

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

Спецификации Статус Коментар
ECMAScript 2015 (6th Edition, ECMA-262)
The definition of 'Arrow Function Definitions' in that specification.
Standard Initial definition.
ECMAScript Latest Draft (ECMA-262)
The definition of 'Arrow Function Definitions' in that specification.
Draft  

Съвместимост с браузера

Update compatibility data on GitHub
DesktopMobileServer
ChromeEdgeFirefoxInternet ExplorerOperaSafariAndroid webviewChrome for AndroidEdge MobileFirefox for AndroidOpera for AndroidSafari on iOSSamsung InternetNode.js
Basic supportChrome Full support 45Edge Full support YesFirefox Full support 22
Notes
Full support 22
Notes
Notes The initial implementation of arrow functions in Firefox made them automatically strict. This has been changed as of Firefox 24. The use of 'use strict'; is now required.
Notes Prior to Firefox 39, a line terminator (\n) was incorrectly allowed after arrow function arguments. This has been fixed to conform to the ES2015 specification and code like () \n => {} will now throw a SyntaxError in this and later versions.
IE No support NoOpera Full support 32Safari Full support 10WebView Android Full support 45Chrome Android Full support 45Edge Mobile Full support YesFirefox Android Full support 22
Notes
Full support 22
Notes
Notes The initial implementation of arrow functions in Firefox made them automatically strict. This has been changed as of Firefox 24. The use of 'use strict'; is now required.
Notes Prior to Firefox 39, a line terminator (\n) was incorrectly allowed after arrow function arguments. This has been fixed to conform to the ES2015 specification and code like () \n => {} will now throw a SyntaxError in this and later versions.
Opera Android Full support 32Safari iOS Full support 10Samsung Internet Android Full support 5.0nodejs Full support Yes
Trailing comma in parametersChrome Full support 58Edge ? Firefox Full support 52IE No support NoOpera Full support 45Safari ? WebView Android Full support 58Chrome Android Full support 58Edge Mobile ? Firefox Android Full support 52Opera Android Full support 45Safari iOS ? Samsung Internet Android Full support 7.0nodejs Full support Yes

Legend

Full support  
Full support
No support  
No support
Compatibility unknown  
Compatibility unknown
See implementation notes.
See implementation notes.

Вижте още

Етикети за документа и сътрудници

Допринесли за тази страница: MTeRzY
Последно обновяване от: MTeRzY,