1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
|
---
title: Arrow functions
slug: Web/JavaScript/Reference/Functions/Arrow_functions
tags:
- Средно напреднали
- Функции
- Функции със стрелка
- референция
translation_of: Web/JavaScript/Reference/Functions/Arrow_functions
---
<div>{{jsSidebar("Functions")}}</div>
<p>Функционалният израз със стрелка има по-кратък синтаксис, отколкото стандартното дефиниране на функция и няма свой собствен <code><a href="/en-US/docs/Web/JavaScript/Reference/Operators/this">this</a></code>, <code><a href="/en-US/docs/Web/JavaScript/Reference/Functions/arguments">arguments</a></code>, <code><a href="/en-US/docs/Web/JavaScript/Reference/Operators/super">super</a></code>, или <code><a href="/en-US/docs/Web/JavaScript/Reference/Operators/new.target">new.target</a></code>. Тези функции не са подходящи за изполване като метод функции(methods) и не могат да бъдат използвани като конструктори.</p>
<div>{{EmbedInteractiveExample("pages/js/functions-arrow.html")}}</div>
<h2 id="Синтаксис">Синтаксис</h2>
<h3 id="Основен_синтаксис">Основен синтаксис</h3>
<pre class="syntaxbox notranslate">(param1, param2, …, paramN) => { statements }
(param1, param2, …, paramN) => expression
// равнозначно на: => { return expression; }
// Скобите не са задължителни, когато има само един входен параметър:
(singleParam) => { statements }
singleParam => { statements }
// Списъка с аргументи за функции без аргументи трябва да бъде написан, като се използват скоби.
() => { statements }
</pre>
<h3 id="Напреднал_синтаксис">Напреднал синтаксис</h3>
<pre class="syntaxbox notranslate">// Резултата може да бъде ограден в скоби за да бъде върнат под формата на обект(object literal expression):
params => ({foo: bar})
// Поддържат се <a href="/en-US/docs/Web/JavaScript/Reference/Functions/rest_parameters">Rest </a>оператора и <a href="en-US/docs/Web/JavaScript/Reference/Functions/Default_parameters">параметри по подразбиране</a>
(param1, param2, ...rest) => { statements }
(param1 = defaultValue1, param2, …, paramN = defaultValueN) => {
statements }
// <a href="/en-US/docs/Web/JavaScript/Reference/Operators/Destructuring_assignment">Деструктуриране</a> на списъка с входни аргументи също се поддържа
var f = ([a, b] = [1, 2], {x: c} = {x: a + b}) => a + b + c;
f(); // 6
</pre>
<h2 id="Описание">Описание</h2>
<p>Вижте също <a href="https://hacks.mozilla.org/2015/06/es6-in-depth-arrow-functions/">"ES6 In Depth: Arrow functions" on hacks.mozilla.org</a>.</p>
<p>Два фактора повлияха за въвеждането на функциите със стрелка: по-къси функции и липсата на ключовата дума <code>this</code>.</p>
<h3 id="По-кракти_функции">По-кракти функции</h3>
<pre class="brush: js notranslate">var elements = [
'Hydrogen',
'Helium',
'Lithium',
'Beryllium'
];
elements.<a href="/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/map">map</a>(function(element) {
return element.length;
}); // извикването на описания код ще върне следния масив: [8, 6, 7, 9]
// Горе описаната функция може да бъде написана и като функция със стрелка по следния начин
elements.map((element) => {
return element.length;
}); // [8, 6, 7, 9]
// Когато има само един входен параметър можем да премахнем скобите:
elements.<a href="/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/map">map</a>(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.<a href="/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/map">map</a>(({ "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.<a href="/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/map">map</a>(({ length }) => length); // [8, 6, 7, 9]
</pre>
<h3 id="Без_отделна_ключова_дума_this">Без отделна ключова дума <code>this</code></h3>
<p>Допреди функциите със стрелка, всяка нова функция дефинираше своя собствена стойност <code><a href="/en-US/docs/Web/JavaScript/Reference/Operators/this">this</a></code> (въз основа на това как се нарича функцията, нов обект в случай на конструктор, недифинарна при извикване на функции в <a href="/en-US/docs/Web/JavaScript/Reference/Strict_mode">строг режим</a>,основният обект ако функцията се извиква като "object method", etc.). Това се оказа по-малко от идеалното с обектно-ориентирания стил на програмиране.</p>
<pre class="brush: js notranslate">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();</pre>
<p>В ECMAScript 3/5, проблемът с <code>this</code> беше поправим като присвоим стойността на <code>this</code> към променлива , която може да бъде затворена.</p>
<pre class="brush: js notranslate">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);
}</pre>
<p>Като алтернатива, може да бъде създадена <a href="/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/bind">свързана функция</a> така че <code>this</code> стойността може да бъде предадена на свързаната целева функция (функцията <code>growUp()</code> в примера по-горе).</p>
<p>Функцията със стрелка няма свой собствен <code>this;</code> Стойността <code>this</code> от използвания лексикален контекст и др. <span style="background-color: #ffffff; color: #212121; display: inline !important; float: none; font-family: arial,sans-serif; font-size: 16px; font-style: normal; font-weight: 400; letter-spacing: normal; text-align: left; text-decoration-style: initial; text-indent: 0px; text-transform: none; white-space: pre-wrap;">Функциите със стрелки следват </span>нормалните правила на промелнива. Така че, докато търсим за <code>this,</code> който не присъства в текущият обхват на функцията, те взимат <code>this</code> от околният обхват. По този начин,в следния код, <code>this</code> <span lang="bg">в рамките на функцията</span>, която се предава на <code>setInterval</code> функцията, има същата стойност като на тази в околната лексикална функция:</p>
<pre class="brush: js notranslate">function Person(){
this.age = 0;
setInterval(() => {
this.age++; // |this| properly refers to the Person object
}, 1000);
}
var p = new Person();</pre>
<h4 id="Връзка_със_строг_режим">Връзка със строг режим</h4>
<p>Като се има в предвид , че <code>this</code> идва от околния лексикален контекст, <a href="/en-US/docs/Web/JavaScript/Reference/Strict_mode">строгите правила за режима</a> по отношение на <code>this</code> се игнорират.</p>
<pre class="brush: js notranslate">var f = () => { 'use strict'; return this; };
f() === window; // or the global object</pre>
<p><span lang="bg">Всички други правила за строг режим се прилагат нормално</span></p>
<h4 id="Извикване_чрез_повикване_или_прилагане">Извикване чрез повикване или прилагане</h4>
<p>Тъй като функциите със стрелка нямат свой собствен <code>this</code>, методите <code>call()</code> <code>или apply()</code> могат само да предават параметри. <code>thisArg</code> се игнорира.</p>
<pre class="brush: js notranslate">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</pre>
<h3 id="Без_обвързване_на_arguments">Без обвързване на <code>arguments</code></h3>
<p>Функциите със стрелка нямат свой собствен <a href="/en-US/docs/Web/JavaScript/Reference/Functions/arguments">обект</a> от <a href="/en-US/docs/Web/JavaScript/Reference/Functions/arguments"><code>аргументи</code> </a>.<span style="background-color: #ffffff; color: #212121; display: inline !important; float: none; font-family: arial,sans-serif; font-size: 16px; font-style: normal; font-weight: 400; letter-spacing: normal; text-align: left; text-decoration-style: initial; text-indent: 0px; text-transform: none; white-space: pre-wrap;">Следователно в този пример <code>аргументите </code>са просто препратка към аргументите на заобикалящото ги поле</span>:</p>
<pre class="brush: js notranslate">var arguments = [1, 2, 3];
var arr = () => arguments[0];
arr(); // 1
function foo(n) {
var f = () => arguments[0] + n; // <em>foo</em>'s implicit arguments binding. arguments[0] is n
return f();
}
foo(3); // 6</pre>
<p>В повечето случаи, използването на <a href="/en-US/docs/Web/JavaScript/Reference/Functions/rest_parameters">rest parameters(остатъчни параметри)</a> е добра алтернатива от използването на обект с <code>аргументи</code>.</p>
<pre class="brush: js notranslate">function foo(n) {
var f = (...args) => args[0] + n;
return f(10);
}
foo(1); // 11</pre>
<h3 id="Функции_със_стрелка_използвани_като_методи">Функции със стрелка използвани като методи</h3>
<p><span class="tlid-translation translation"><span title="">Както бе посочено по-горе, изразите на функциите със стрелките са най-подходящи за функциите, различни от метода.</span> <span title="">Нека видим какво се случва, когато се опитаме да ги използваме като методи:</span></span></p>
<pre class="brush: js notranslate">'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 {...}</pre>
<p>Функциите със стрелка нямат свой собствен <code>this</code>. Друг пример затова е : {{jsxref("Object.defineProperty()")}}:</p>
<pre class="brush: js notranslate">'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'
}
});
</pre>
<h3 id="Използване_на_оператора_new">Използване на оператора <code>new</code></h3>
<p>Функциите със стрелка не мога да бъдат използвани като конструктории ще генерират грешка , когато се изпозват с оператора <code>new</code>.</p>
<pre class="brush: js notranslate">var Foo = () => {};
var foo = new Foo(); // TypeError: Foo is not a constructor</pre>
<h3 id="Използване_на_свойството_prototype">Използване на свойството <code>prototype</code></h3>
<p>Функциите със стрелки нямат свойството <code>prototype</code>.</p>
<pre class="brush: js notranslate">var Foo = () => {};
console.log(Foo.prototype); // undefined
</pre>
<h3 id="Използване_на_ключовата_дума_yield">Използване на ключовата дума <code>yield</code></h3>
<p><span class="tlid-translation translation"><span title="">Ключовата дума</span></span> <code><a href="/en-US/docs/Web/JavaScript/Reference/Operators/yield">yield</a></code> не може да бъде използвана в тялото на функцията със стрелка ( <span class="tlid-translation translation"><span title="">освен когато е позволено в рамките на функциите, които са вложени в нея</span></span> ). <span class="tlid-translation translation"><span title="">В резултат на това функциите със стрелки не могат да се използват като генератори.</span></span></p>
<h2 id="Тялото_на_функция">Тялото на функция</h2>
<p>Функциите със стрелка могат да имат или "сбито тяло" или обичайното "блоково тяло".</p>
<p>В сбитото тяло е посочен само израз, който се превръща в неявна връщана стойност. <span class="tlid-translation translation"><span title="">В блоково тяло трябва да използвате изрично <code>return</code> декларация за връщане.</span></span></p>
<pre class="brush: js notranslate">var func = x => x * x;
// concise body syntax, implied "return"
var func = (x, y) => { return x + y; };
// with block body, explicit "return" needed
</pre>
<h2 id="Връщане_на_литерали_на_обекти">Връщане на литерали на обекти</h2>
<p>Имайте в предвид , че връщането на литерали на обекти, използвайки сбит синтаксис <code>params => {object:literal}</code> няма да работи според очакванията.</p>
<pre class="brush: js notranslate">var func = () => { foo: 1 };
// Calling func() returns undefined!
var func = () => { foo: function() {} };
// SyntaxError: function statement requires a name</pre>
<p>Това е защото кодът вътре в скобите ({}) се анализита като оследователност от изрази (или <code>foo</code>се третира като етикет, а не като ключ в буквален обект).</p>
<p>Запомнете, че трябва да поставяте буквалният обект в скоби , както е показано в примера по-долу.</p>
<pre class="brush: js notranslate">var func = () => ({foo: 1});</pre>
<h2 id="Прекъсване_на_линията">Прекъсване на линията</h2>
<p>Функцията със стрелка не може да съдържа прекъсната линия между нейните параметри и стрелка.</p>
<pre class="brush: js notranslate">var func = (a, b, c)
=> 1;
// SyntaxError: expected expression, got '=>'</pre>
<p><span class="tlid-translation translation"><span title="">Все пак това може да бъде променено, чрез използване на скоби или поставяне на разделителната линия в аргументите, както е показано в примера по-долу, за да се гарантира, че кодът остава красив и пухкав.</span></span></p>
<pre class="brush: js notranslate">var func = (
a,
b,
c
) => (
1
);
// no SyntaxError thrown</pre>
<h2 id="Parsing_order">Parsing order</h2>
<p>Въпреки че, стрелката във функцията със стрелка не е оператор, функциите със стрелка имат специални правила, които взаимодействат по различен начин с <a href="/en-US/docs/Web/JavaScript/Reference/Operators/Operator_Precedence">оператора за предимство </a> сравнено с нормалните функции.</p>
<pre class="brush: js notranslate">let callback;
callback = callback || function() {}; // ok
callback = callback || () => {};
// SyntaxError: invalid arrow-function arguments
callback = callback || (() => {}); // ok
</pre>
<h2 id="Още_примери">Още примери</h2>
<pre class="brush: js notranslate">// 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);
</pre>
<h2 id="Спецификации">Спецификации</h2>
<table class="standard-table">
<tbody>
<tr>
<th scope="col">Спецификации</th>
<th scope="col">Статус</th>
<th scope="col">Коментар</th>
</tr>
<tr>
<td>{{SpecName('ES2015', '#sec-arrow-function-definitions', 'Arrow Function Definitions')}}</td>
<td>{{Spec2('ES2015')}}</td>
<td>Initial definition.</td>
</tr>
<tr>
<td>{{SpecName('ESDraft', '#sec-arrow-function-definitions', 'Arrow Function Definitions')}}</td>
<td>{{Spec2('ESDraft')}}</td>
<td></td>
</tr>
</tbody>
</table>
<h2 id="Съвместимост_с_браузера">Съвместимост с браузера</h2>
<div>
<p>{{Compat("javascript.functions.arrow_functions")}}</p>
</div>
<h2 id="Вижте_още">Вижте още</h2>
<ul>
<li><a href="https://hacks.mozilla.org/2015/06/es6-in-depth-arrow-functions/">"ES6 In Depth: Arrow functions" on hacks.mozilla.org</a></li>
</ul>
|