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
Copy file name to clipboardExpand all lines: 1-js/02-first-steps/16-function-expressions/article.md
+48-37Lines changed: 48 additions & 37 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -12,19 +12,31 @@ function sayHi() {
12
12
13
13
Существует ещё один синтаксис создания функций, который называется *Function Expression* (Функциональное Выражение).
14
14
15
-
Оно выглядит вот так:
15
+
Данный синтаксис позволяет нам создавать новую функцию в середине любого выражения.
16
+
17
+
Это выглядит следующим образом:
16
18
17
19
```js
18
20
letsayHi=function() {
19
21
alert( "Привет" );
20
22
};
21
23
```
22
24
23
-
В коде выше функция создаётся и явно присваивается переменной, как любое другое значение. По сути без разницы, как мы определили функцию, это просто значение, хранимое в переменной `sayHi`.
25
+
Здесь мы можем видеть переменную `sayHi`, получающую значение, новую функцию, созданную как `function() { alert("Привет"); }`.
26
+
27
+
Поскольку создание функции происходит в контексте выражения присваивания (с правой стороны от `=`), это *Function Expression*.
28
+
29
+
Обратите внимание, что после ключевого слова `function` нет имени. Для Function Expression допускается его отсутствие.
30
+
31
+
Здесь мы сразу присваиваем её переменной, так что смысл этих примеров кода один и тот же: "создать функцию и поместить её в переменную `sayHi`".
32
+
33
+
В более сложных ситуациях, с которыми мы столкнёмся позже, функция может быть создана и немедленно вызвана, или запланирована для дальнейшего выполнения, нигде не сохраняясь, таким образом, оставаясь анонимной.
24
34
25
-
Смысл обоих примеров кода одинаков: "создать функцию и поместить её значение в переменную `sayHi`".
35
+
## Функция - это значение
26
36
27
-
Мы можем даже вывести это значение с помощью `alert`:
37
+
Давайте повторим: независимо от того, как создаётся функция - она является значением. В обоих приведённых выше примерах функция хранится в переменной `sayHi`.
38
+
39
+
Мы даже можем вывести это значение с помощью `alert`:
28
40
29
41
```js run
30
42
functionsayHi() {
@@ -35,14 +47,13 @@ function sayHi() {
35
47
alert( sayHi ); // выведет код функции
36
48
*/!*
37
49
```
50
+
Обратите внимание, что последняя строка не вызывает функцию, потому что после `sayHi` нет круглых скобок. Существуют языки программирования, в которых любое упоминание имени функции приводит к её выполнению, но JavaScript к таким не относится.
38
51
39
-
Обратите внимание, что последняя строка не вызывает функцию `sayHi`, после её имени нет круглых скобок. Существуют языки программирования, в которых любое упоминание имени функции совершает её вызов. JavaScript - не один из них.
40
-
41
-
В JavaScript функции - это значения, поэтому мы и обращаемся с ними, как со значениями. Код выше выведет строковое представление функции, которое является её исходным кодом.
52
+
В JavaScript функция - это значение, поэтому мы можем обращаться с ней как со значением. Приведённый выше код показывает её строковое представление, которое является её исходным кодом.
42
53
43
-
Конечно, функция - не обычное значение, в том смысле, что мы можем вызвать его при помощи скобок:`sayHi()`.
54
+
Конечно, функция - это особое значение, в том смысле, что мы можем вызвать её как`sayHi()`.
44
55
45
-
Но всё же это значение. Поэтому мы можем делать с ним то же самое, что и с любым другим значением.
56
+
Но всё же это значение. Поэтому мы можем работать с ней так же, как и с другими видами значений.
46
57
47
58
Мы можем скопировать функцию в другую переменную:
48
59
@@ -53,28 +64,28 @@ function sayHi() { // (1) создаём
sayHi(); // Привет // эта тоже все ещё работает (почему бы и нет)
58
69
```
59
70
60
71
Давайте подробно разберём всё, что тут произошло:
61
72
62
-
1. Объявление Function Declaration `(1)`создало функцию и присвоило её значение переменной с именем `sayHi`.
73
+
1. Объявление Function Declaration `(1)`создаёт функцию и помещает её в переменную с именем `sayHi`.
63
74
2. В строке `(2)` мы скопировали её значение в переменную `func`. Обратите внимание (ещё раз): нет круглых скобок после `sayHi`. Если бы они были, то выражение `func = sayHi()` записало бы *результат вызова*`sayHi()` в переменную `func`, а не саму *функцию*`sayHi`.
64
-
3. Теперь функция может быть вызвана с помощью обеих переменных `sayHi()`и `func()`.
75
+
3. Теперь функция может вызываться как `sayHi()`, так и `func()`.
65
76
66
-
Заметим, что мы могли бы использовать и Function Expression для того, чтобы создать`sayHi` в первой строке:
77
+
Мы также могли бы использовать Function Expression для объявления`sayHi` в первой строке:
67
78
68
79
```js
69
-
letsayHi=function() {
80
+
letsayHi=function() {// (1) создаём
70
81
alert( "Привет" );
71
82
};
72
83
73
84
let func = sayHi;
74
85
// ...
75
86
```
76
87
77
-
Результат был бы таким же.
88
+
Всё будет работать так же.
78
89
79
90
````smart header="Зачем нужна точка с запятой в конце?"
80
91
У вас мог возникнуть вопрос: Почему в Function Expression ставится точка с запятой `;` на конце, а в Function Declaration нет:
@@ -89,14 +100,14 @@ let sayHi = function() {
89
100
}*!*;*/!*
90
101
```
91
102
92
-
Ответ прост:
93
-
- Нет необходимости в `;` в конце блоков кода и синтаксических конструкций, которые их используют, таких как `if { ... }`, `for { }`, `function f { }` и т.д.
94
-
- Function Expression использует внутри себя инструкции присваивания`let sayHi = ...;` как значение. Это не блок кода, а выражение с присваиванием. Таким образом, точка с запятой не относится непосредственно к Function Expression, она лишь завершает инструкцию.
103
+
Ответ прост: Function Expression создаётся здесь как `function(...) {...}` внутри выражения присваивания: `let sayHi = …;`. Точку с запятой `;` рекомендуется ставить в конце выражения, она не является частью синтаксиса функции.
104
+
105
+
Точка с запятой нужна там для более простого присваивания, такого как `let sayHi = 5;`, а также для присваивания функции.
95
106
````
96
107
97
108
## Функции-"колбэки"
98
109
99
-
Рассмотрим ещё примеры функциональных выражений и передачи функции как значения.
110
+
Давайте рассмотрим больше примеров передачи функции в виде значения и использования функциональных выражений.
100
111
101
112
Давайте напишем функцию `ask(question, yes, no)` с тремя параметрами:
На практике подобные функции очень полезны. Основное отличие "реальной" функции `ask` от примера выше будет в том, что она использует более сложные способы взаимодействия с пользователем, чем простой вызов `confirm`. В браузерах такие функции обычно отображают красивые диалоговые окна. Но это уже другая история.
135
146
136
-
**Аргументы функции `ask`ещё называют*функциями-колбэками* или просто *колбэками*.**
147
+
**Аргументы `showOk` и `showCancel`функции `ask`называются*функциями-колбэками* или просто *колбэками*.**
137
148
138
149
Ключевая идея в том, что мы передаём функцию и ожидаем, что она вызовется обратно (от англ. "call back" - обратный вызов) когда-нибудь позже, если это будет необходимо. В нашем случае, `showOk` становится *колбэком* для ответа "yes", а `showCancel` -- для ответа "no".
139
150
@@ -164,7 +175,7 @@ ask(
164
175
```smart header="Функция - это значение, представляющее \"действие\""
165
176
Обычные значения, такие как строки или числа представляют собой *данные*.
166
177
167
-
Функции, с другой стороны, можно воспринимать как "действия".
178
+
Функции, с другой стороны, можно воспринимать как *действия*.
168
179
169
180
Мы можем передавать их из переменной в переменную и запускать, когда захотим.
170
181
```
@@ -174,17 +185,17 @@ ask(
174
185
175
186
Давайте разберём ключевые отличия Function Declaration от Function Expression.
176
187
177
-
Во-первых, синтаксис: как определить, что есть что в коде.
188
+
Во-первых, синтаксис: как отличить их друг от друга в коде.
178
189
179
-
- Function Declaration: функция объявляется отдельной конструкцией "function..." в основном потоке кода.
190
+
-*Function Declaration*: функция объявляется отдельной конструкцией "function..." в основном потоке кода.
180
191
181
192
```js
182
193
// Function Declaration
183
194
functionsum(a, b) {
184
195
return a + b;
185
196
}
186
197
```
187
-
-Function Expression: функция, созданная внутри другого выражения или синтаксической конструкции. В данном случае функция создаётся в правой части "выражения присваивания"`=`:
198
+
-*Function Expression*: функция, созданная внутри другого выражения или синтаксической конструкции. В данном случае функция создаётся в правой части "выражения присваивания"`=`:
188
199
189
200
```js
190
201
// Function Expression
@@ -201,7 +212,7 @@ ask(
201
212
202
213
С Function Declaration всё иначе.
203
214
204
-
**Function Declaration можно использовать во всем скрипте (или блоке кода, если функция объявлена в блоке).**
215
+
**Function Declaration может быть вызвана раньше, чем она объявлена.**
205
216
206
217
Другими словами, когда движок JavaScript *готовится* выполнять скрипт или блок кода, прежде всего он ищет в нём Function Declaration и создаёт все такие функции. Можно считать этот процесс "стадией инициализации".
207
218
@@ -241,9 +252,9 @@ let sayHi = function(name) { // (*) магии больше нет
241
252
242
253
**В строгом режиме, когда Function Declaration находится в блоке `{...}`, функция доступна везде внутри блока. Но не снаружи него.**
243
254
244
-
Для примера давайте представим, что нам нужно создать функцию `welcome()` в зависимости от значения переменной `age`, которое мы получим во время выполнения кода. И затем запланируем использовать её когда-нибудь в будущем.
255
+
Для примера давайте представим, что нам нужно объявить функцию `welcome()` в зависимости от значения переменной `age`, которое мы получим во время выполнения кода. И затем запланируем использовать её когда-нибудь в будущем.
245
256
246
-
Такой код, использующий Function Declaration, работать не будет:
257
+
Если мы попробуем использовать Function Declaration, это не заработает так, как задумывалось:
247
258
248
259
```js run
249
260
let age = prompt("Сколько Вам лет?", 18);
@@ -274,7 +285,7 @@ welcome(); // Error: welcome is not defined
274
285
Вот ещё один пример:
275
286
276
287
```js run
277
-
let age = 16; // присвоим для примера 16
288
+
let age = 16; // возьмём для примера 16
278
289
279
290
if (age < 18) {
280
291
*!*
@@ -308,7 +319,7 @@ welcome(); // Ошибка: welcome is not defined
308
319
309
320
Верным подходом будет воспользоваться функцией, объявленной при помощи Function Expression, и присвоить значение `welcome` переменной, объявленной снаружи `if`, что обеспечит нам нужную видимость.
310
321
311
-
Такой код работает, как ожидалось:
322
+
Такой код заработает, как ожидалось:
312
323
313
324
```js run
314
325
let age = prompt("Сколько Вам лет?", 18);
@@ -334,7 +345,7 @@ welcome(); // теперь всё в порядке
334
345
*/!*
335
346
```
336
347
337
-
Можно упростить этот код ещё сильнее, используя условный оператор `?`:
348
+
Или мы могли бы упростить это ещё сильнее, используя условный оператор `?`:
338
349
339
350
```js run
340
351
let age = prompt("Сколько Вам лет?", 18);
@@ -354,17 +365,17 @@ welcome(); // теперь всё в порядке
354
365
355
366
Также функции вида `functionf(…) {…}` чуть более заметны в коде, чем `letf=function(…) {…}`. Function Declaration легче "ловятся глазами".
356
367
357
-
...Но если Function Declaration нам не подходит по какой-то причине(мы рассмотрели это в примере выше), то можно использовать объявление при помощи Function Expression.
368
+
...Но если Function Declaration нам не подходит по какой-то причине, или нам нужно условное объявление (мы рассмотрели это в примере выше), то следует использовать Function Expression.
358
369
```
359
370
360
371
## Итого
361
372
362
373
- Функции - это значения. Они могут быть присвоены, скопированы или объявлены в любом месте кода.
363
-
- Если функция объявлена как отдельная инструкция в основном потоке кода, то это Function Declaration.
364
-
- Если функция была создана как часть выражения, то считается, что эта функция объявлена при помощи Function Expression.
374
+
- Если функция объявлена как отдельная инструкция в основном потоке кода, то это “Function Declaration”.
375
+
- Если функция была создана как часть выражения, то это “Function Expression”.
365
376
-Function Declaration обрабатываются перед выполнением блока кода. Они видны во всём блоке.
366
-
- Функции, объявленные при помощи Function Expression, создаются, только когда поток выполнения достигает их.
377
+
- Функции, объявленные при помощи Function Expression, создаются только когда поток выполнения достигает их.
367
378
368
-
В большинстве случаев, когда нам нужно создать функцию, предпочтительно использовать Function Declaration, т.к. функция будет видима до своего объявления в коде. Это позволяет более гибко организовывать код и улучшает его читаемость.
379
+
В большинстве случаев, когда нам нужно объявить функцию, Function Declaration предпочтительнее, т.к функция будет видна до своего объявления в коде. Это даёт нам больше гибкости в организации кода и, как правило, делает его более читабельным.
369
380
370
-
Таким образом, мы должны прибегать к объявлению функций при помощи Function Expression в случае, когда синтаксис Function Declaration не подходит для нашей задачи. Мы рассмотрели несколько таких примеров в этой главе, и рассмотрим их ещё больше в будущем.
381
+
Исходя из этого, мы должны использовать Function Expression только тогда, когда Function Declaration не подходит для нашей задачи. Мы рассмотрели несколько таких примеров в этой главе, и увидим ещё больше в будущем.
0 commit comments