From 4b1a9203c547c019fc5398082ae19a3f3d4c3efe Mon Sep 17 00:00:00 2001 From: Peter Bengtsson Date: Tue, 8 Dec 2020 14:41:15 -0500 Subject: initial commit --- .../reference/functions/arrow_functions/index.html | 394 +++++++++++++++++++++ 1 file changed, 394 insertions(+) create mode 100644 files/bg/web/javascript/reference/functions/arrow_functions/index.html (limited to 'files/bg/web/javascript/reference/functions/arrow_functions/index.html') diff --git a/files/bg/web/javascript/reference/functions/arrow_functions/index.html b/files/bg/web/javascript/reference/functions/arrow_functions/index.html new file mode 100644 index 0000000000..f2efe8ec10 --- /dev/null +++ b/files/bg/web/javascript/reference/functions/arrow_functions/index.html @@ -0,0 +1,394 @@ +--- +title: Arrow functions +slug: Web/JavaScript/Reference/Functions/Arrow_functions +tags: + - Средно напреднали + - Функции + - Функции със стрелка + - референция +translation_of: Web/JavaScript/Reference/Functions/Arrow_functions +--- +
{{jsSidebar("Functions")}}
+ +

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

+ +
{{EmbedInteractiveExample("pages/js/functions-arrow.html")}}
+ +

Синтаксис

+ +

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

+ +
(param1, param2, …, paramN) => { statements }
+(param1, param2, …, paramN) => expression
+// равнозначно на: => { return expression; }
+
+// Скобите не са задължителни, когато има само един входен параметър:
+(singleParam) => { statements }
+singleParam => { statements }
+
+// Списъка с аргументи за функции без аргументи трябва да бъде написан, като се използват скоби.
+() => { statements }
+
+ +

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

+ +
// Резултата може да бъде ограден в скоби за да бъде върнат под формата на обект(object literal expression):
+params => ({foo: bar})
+
+// Поддържат се Rest оператора и параметри по подразбиране
+(param1, param2, ...rest) => { statements }
+(param1 = defaultValue1, param2, …, paramN = defaultValueN) => {
+statements }
+
+// Деструктуриране на списъка с входни аргументи също се поддържа
+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;
+}); // извикването на описания код ще върне следния масив: [8, 6, 7, 9]
+
+// Горе описаната функция може да бъде написана и като функция със стрелка по следния начин
+elements.map((element) => {
+  return element.length;
+}); // [8, 6, 7, 9]
+
+// Когато има само един входен параметър можем да премахнем скобите:
+elements.map(element => {
+  return element.length;
+}); // [8, 6, 7, 9]
+
+// Когато единственото нещо в функцията е връщане на резултат, можем да премахнем `return`
+//  и също така да премахнем скобите
+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. Друг пример затова е : {{jsxref("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);
+
+ +

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

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

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

+ +
+ + +

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

+
+ +

Вижте още

+ + -- cgit v1.2.3-54-g00ecf