You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
@@ -237,304 +237,50 @@ In the code above, the whole arguments object is `{}` by default, so there's alw
237
237
238
238
## The spread operator
239
239
240
-
// TODO!!!
240
+
As we've seen before, the rest operator `...` allows to gather parameters in the array.
241
241
242
-
Выше мы увидели использование `...` для чтения параметров в объявлении функции. Но этот же оператор можно использовать и при вызове функции, для передачи массива параметров как списка, например:
242
+
But there's a reverse named "the spread operator". It also looks like `...` and works at call-time.
243
243
244
-
```js run
245
-
'use strict';
246
-
247
-
let numbers = [2, 3, 15];
248
-
249
-
// Оператор ... в вызове передаст массив как список аргументов
250
-
// Этот вызов аналогичен Math.max(2, 3, 15)
251
-
let max =Math.max(*!*...numbers*/!*);
252
-
253
-
alert( max ); // 15
254
-
```
255
-
256
-
Формально говоря, эти два вызова делают одно и то же:
257
-
258
-
```js
259
-
Math.max(...numbers);
260
-
Math.max.apply(Math, numbers);
261
-
```
262
-
263
-
Похоже, что первый -- короче и красивее.
264
-
265
-
## Деструктуризация в параметрах
266
-
267
-
268
-
## Имя "name"
269
-
270
-
В свойстве `name` у функции находится её имя.
271
-
272
-
Например:
244
+
The spread operator allows to "unfurl" an array into a list of parameters, like this:
273
245
274
246
```js run
275
-
'use strict';
276
-
277
-
functionf() {} // f.name == "f"
278
-
279
-
letg=functiong() {}; // g.name == "g"
280
-
281
-
alert(f.name+''+g.name) // f g
282
-
```
283
-
284
-
В примере выше показаны Function Declaration и Named Function Expression. В синтаксисе выше довольно очевидно, что у этих функций есть имя `name`. В конце концов, оно указано в объявлении.
285
-
286
-
Но современный JavaScript идёт дальше, он старается даже анонимным функциям дать разумные имена.
287
-
288
-
Например, при создании анонимной функции с одновременной записью в переменную или свойство -- её имя равно названию переменной (или свойства).
289
-
290
-
Например:
291
-
292
-
```js
293
-
'use strict';
294
-
295
-
// свойство g.name = "g"
296
-
letg=function() {};
297
-
298
-
let user = {
299
-
// свойство user.sayHi.name == "sayHi"
300
-
sayHi:function() {}
301
-
};
302
-
```
303
-
304
-
## Функции в блоке
305
-
306
-
Объявление функции Function Declaration, сделанное в блоке, видно только в этом блоке.
То есть, иными словами, такое объявление -- ведёт себя в точности как если бы `let sayHi = function() {…}` было сделано в начале блока.
326
-
327
-
## Функции через =>
328
-
329
-
Появился новый синтаксис для задания функций через "стрелку" `=>`.
330
-
331
-
Его простейший вариант выглядит так:
332
-
```js run
333
-
'use strict';
334
254
335
-
*!*
336
-
letinc=x=> x+1;
337
-
*/!*
338
-
339
-
alert( inc(1) ); // 2
255
+
// The spread operator ... passes an array as a list of arguments
256
+
showName(...fullName);
340
257
```
341
258
342
-
Эти две записи -- примерно аналогичны:
343
-
344
-
```js
345
-
letinc=x=> x+1;
346
-
347
-
letinc=function(x) { return x +1; };
348
-
```
349
259
350
-
Как видно, `"x => x+1"` -- это уже готовая функция. Слева от `=>` находится аргумент, а справа -- выражение, которое нужно вернуть.
260
+
Let's see a more real-life example.
351
261
352
-
Если аргументов несколько, то нужно обернуть их в скобки, вот так:
262
+
There exist a built-in function [Math.max](mdn:js/Math/max) that takes a list of values and returns the greatest one:
353
263
354
264
```js run
355
-
'use strict';
356
-
357
-
*!*
358
-
letsum= (a,b) => a + b;
359
-
*/!*
360
-
361
-
// аналог с function
362
-
// let inc = function(a, b) { return a + b; };
363
-
364
-
alert( sum(1, 2) ); // 3
265
+
alert( Math.max(5, 7, -8, 1) ); // 7
365
266
```
366
267
367
-
Если нужно задать функцию без аргументов, то также используются скобки, в этом случае -- пустые:
268
+
Imagine we have an array and want to select a maximum from it. Unfortunately, `Math.max` works with a list of parameters, not with arrays, so a direct call `Math.max(arr)` won't work. But we can use the spread operator `...` to pass the array as the list:
Когда тело функции достаточно большое, то можно его обернуть в фигурные скобки `{…}`:
381
270
382
271
```js run
383
-
'use strict';
384
-
385
-
*!*
386
-
letgetTime= () => {
387
-
let date =newDate();
388
-
let hours =date.getHours();
389
-
let minutes =date.getMinutes();
390
-
return hourse +':'+ minutes;
391
-
};
392
-
*/!*
272
+
let arr = [5, 7, -8, 1];
393
273
394
-
alert( getTime() ); //текущее время
274
+
alert( Math.max(...arr) ); //7
395
275
```
396
276
397
-
Заметим, что как только тело функции оборачивается в `{…}`, то её результат уже не возвращается автоматически. Такая функция должна делать явный `return`, как в примере выше, если конечно хочет что-либо возвратить.
277
+
In short:
278
+
- When `...` occurs in function parameters, it's called a "rest operator" and gathers parameters into the array.
279
+
- When `...` occurs in a function call, it's called a "spread operator" and unfurls an array into the list.
398
280
399
-
Функции-стрелки очень удобны в качестве коллбеков, например:
400
-
401
-
```js run
402
-
`use strict`;
281
+
Together they help to travel between a list and an array of parameters with ease.
403
282
404
-
let arr = [5, 8, 3];
405
-
406
-
*!*
407
-
let sorted =arr.sort( (a,b) => a - b );
408
-
*/!*
409
-
410
-
alert(sorted); // 3, 5, 8
411
-
```
412
-
413
-
Такая запись -- коротка и понятна. Далее мы познакомимся с дополнительными преимуществами использования функций-стрелок для этой цели.
414
-
415
-
## Функции-стрелки не имеют своего this
416
-
417
-
Внутри функций-стрелок -- тот же `this`, что и снаружи.
418
-
419
-
Это очень удобно в обработчиках событий и коллбэках, например:
420
-
421
-
```js run
422
-
'use strict';
423
-
424
-
let group = {
425
-
title:"Наш курс",
426
-
students: ["Вася", "Петя", "Даша"],
427
-
428
-
showList:function() {
429
-
*!*
430
-
this.students.forEach(
431
-
student=>alert(this.title+': '+ student)
432
-
)
433
-
*/!*
434
-
}
435
-
}
436
-
437
-
group.showList();
438
-
// Наш курс: Вася
439
-
// Наш курс: Петя
440
-
// Наш курс: Даша
441
-
```
442
-
443
-
Здесь в `forEach` была использована функция-стрелка, поэтому `this.title` в коллбэке -- тот же, что и во внешней функции `showList`. То есть, в данном случае -- `group.title`.
444
-
445
-
Если бы в `forEach` вместо функции-стрелки была обычная функция, то была бы ошибка:
446
-
447
-
```js run
448
-
'use strict';
449
-
450
-
let group = {
451
-
title:"Наш курс",
452
-
students: ["Вася", "Петя", "Даша"],
453
-
454
-
showList:function() {
455
-
*!*
456
-
this.students.forEach(function(student) {
457
-
alert(this.title+': '+ student); // будет ошибка
458
-
})
459
-
*/!*
460
-
}
461
-
}
462
-
463
-
group.showList();
464
-
```
465
-
466
-
При запуске будет "попытка прочитать свойство `title` у `undefined`", так как `.forEach(f)` при запуске `f` не ставит `this`. То есть, `this` внутри `forEach` будет `undefined`.
467
-
468
-
```warn header="Функции стрелки нельзя запускать с `new`"
469
-
Отсутствие у функции-стрелки "своего `this`" влечёт за собой естественное ограничение: такие функции нельзя использовать в качестве конструктора, то есть нельзя вызывать через `new`.
470
-
```
471
-
472
-
```smart header="=> это не то же самое, что `.bind(this)`"
473
-
Есть тонкое различие между функцией стрелкой `=>` и обычной функцией, у которой вызван `.bind(this)`:
474
-
475
-
- Вызовом `.bind(this)` мы передаём текущий `this`, привязывая его к функции.
476
-
- При `=>` привязки не происходит, так как функция стрелка вообще не имеет контекста `this`. Поиск `this` в ней осуществляется так же, как и поиск обычной переменной, то есть, выше в замыкании. До появления стандарта ES-2015 такое было невозможно.
477
-
```
478
-
479
-
## Функции-стрелки не имеют своего arguments
480
-
481
-
В качестве `arguments` используются аргументы внешней "обычной" функции.
482
-
483
-
Например:
484
-
485
-
```js run
486
-
'use strict';
487
-
488
-
functionf() {
489
-
letshowArg= () =>alert(arguments[0]);
490
-
showArg();
491
-
}
492
-
493
-
f(1); // 1
494
-
```
495
-
496
-
Вызов `showArg()` выведет `1`, получив его из аргументов функции `f`. Функция-стрелка здесь вызвана без параметров, но это не важно: `arguments` всегда берутся из внешней "обычной" функции.
497
-
498
-
Сохранение внешнего `this` и `arguments` удобно использовать для форвардинга вызовов и создания декораторов.
499
-
500
-
Например, декоратор `defer(f, ms)` ниже получает функцию `f` и возвращает обёртку вокруг неё, откладывающую вызов на `ms` миллисекунд:
501
-
502
-
```js run
503
-
'use strict';
504
-
505
-
*!*
506
-
functiondefer(f, ms) {
507
-
returnfunction() {
508
-
setTimeout(() =>f.apply(this, arguments), ms)
509
-
}
510
-
}
511
-
*/!*
512
-
513
-
functionsayHi(who) {
514
-
alert('Привет, '+ who);
515
-
}
516
-
517
-
let sayHiDeferred =defer(sayHi, 2000);
518
-
sayHiDeferred("Вася"); // Привет, Вася через 2 секунды
519
-
```
520
-
521
-
Аналогичная реализация без функции-стрелки выглядела бы так:
522
-
523
-
```js
524
-
functiondefer(f, ms) {
525
-
returnfunction() {
526
-
*!*
527
-
let args =arguments;
528
-
let ctx =this;
529
-
*/!*
530
-
setTimeout(function() {
531
-
returnf.apply(ctx, args);
532
-
}, ms);
533
-
}
534
-
}
535
-
```
536
283
537
-
В этом коде пришлось создавать дополнительные переменные `args` и `ctx` для передачи внешних аргументов и контекста через замыкание.
0 commit comments