Skip to content

Commit 160f937

Browse files
authored
Merge pull request #1522 from Rnbsov/patch-12
Обновление статьи "Function Expression" в соответствии с английской версией учебника.
2 parents f235e14 + 5927450 commit 160f937

File tree

1 file changed

+48
-37
lines changed
  • 1-js/02-first-steps/16-function-expressions

1 file changed

+48
-37
lines changed

1-js/02-first-steps/16-function-expressions/article.md

Lines changed: 48 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -12,19 +12,31 @@ function sayHi() {
1212

1313
Существует ещё один синтаксис создания функций, который называется *Function Expression* (Функциональное Выражение).
1414

15-
Оно выглядит вот так:
15+
Данный синтаксис позволяет нам создавать новую функцию в середине любого выражения.
16+
17+
Это выглядит следующим образом:
1618

1719
```js
1820
let sayHi = function() {
1921
alert( "Привет" );
2022
};
2123
```
2224

23-
В коде выше функция создаётся и явно присваивается переменной, как любое другое значение. По сути без разницы, как мы определили функцию, это просто значение, хранимое в переменной `sayHi`.
25+
Здесь мы можем видеть переменную `sayHi`, получающую значение, новую функцию, созданную как `function() { alert("Привет"); }`.
26+
27+
Поскольку создание функции происходит в контексте выражения присваивания (с правой стороны от `=`), это *Function Expression*.
28+
29+
Обратите внимание, что после ключевого слова `function` нет имени. Для Function Expression допускается его отсутствие.
30+
31+
Здесь мы сразу присваиваем её переменной, так что смысл этих примеров кода один и тот же: "создать функцию и поместить её в переменную `sayHi`".
32+
33+
В более сложных ситуациях, с которыми мы столкнёмся позже, функция может быть создана и немедленно вызвана, или запланирована для дальнейшего выполнения, нигде не сохраняясь, таким образом, оставаясь анонимной.
2434

25-
Смысл обоих примеров кода одинаков: "создать функцию и поместить её значение в переменную `sayHi`".
35+
## Функция - это значение
2636

27-
Мы можем даже вывести это значение с помощью `alert`:
37+
Давайте повторим: независимо от того, как создаётся функция - она является значением. В обоих приведённых выше примерах функция хранится в переменной `sayHi`.
38+
39+
Мы даже можем вывести это значение с помощью `alert`:
2840

2941
```js run
3042
function sayHi() {
@@ -35,14 +47,13 @@ function sayHi() {
3547
alert( sayHi ); // выведет код функции
3648
*/!*
3749
```
50+
Обратите внимание, что последняя строка не вызывает функцию, потому что после `sayHi` нет круглых скобок. Существуют языки программирования, в которых любое упоминание имени функции приводит к её выполнению, но JavaScript к таким не относится.
3851

39-
Обратите внимание, что последняя строка не вызывает функцию `sayHi`, после её имени нет круглых скобок. Существуют языки программирования, в которых любое упоминание имени функции совершает её вызов. JavaScript - не один из них.
40-
41-
В JavaScript функции - это значения, поэтому мы и обращаемся с ними, как со значениями. Код выше выведет строковое представление функции, которое является её исходным кодом.
52+
В JavaScript функция - это значение, поэтому мы можем обращаться с ней как со значением. Приведённый выше код показывает её строковое представление, которое является её исходным кодом.
4253

43-
Конечно, функция - не обычное значение, в том смысле, что мы можем вызвать его при помощи скобок: `sayHi()`.
54+
Конечно, функция - это особое значение, в том смысле, что мы можем вызвать её как `sayHi()`.
4455

45-
Но всё же это значение. Поэтому мы можем делать с ним то же самое, что и с любым другим значением.
56+
Но всё же это значение. Поэтому мы можем работать с ней так же, как и с другими видами значений.
4657

4758
Мы можем скопировать функцию в другую переменную:
4859

@@ -53,28 +64,28 @@ function sayHi() { // (1) создаём
5364

5465
let func = sayHi; // (2) копируем
5566

56-
func(); // Привет // (3) вызываем копию (работает)!
57-
sayHi(); // Привет // прежняя тоже работает (почему бы нет)
67+
func(); // Привет // (3) вызываем копию (работает)!
68+
sayHi(); // Привет // эта тоже все ещё работает (почему бы и нет)
5869
```
5970

6071
Давайте подробно разберём всё, что тут произошло:
6172

62-
1. Объявление Function Declaration `(1)` создало функцию и присвоило её значение переменной с именем `sayHi`.
73+
1. Объявление Function Declaration `(1)` создаёт функцию и помещает её в переменную с именем `sayHi`.
6374
2. В строке `(2)` мы скопировали её значение в переменную `func`. Обратите внимание (ещё раз): нет круглых скобок после `sayHi`. Если бы они были, то выражение `func = sayHi()` записало бы *результат вызова* `sayHi()` в переменную `func`, а не саму *функцию* `sayHi`.
64-
3. Теперь функция может быть вызвана с помощью обеих переменных `sayHi()` и `func()`.
75+
3. Теперь функция может вызываться как `sayHi()`, так и `func()`.
6576

66-
Заметим, что мы могли бы использовать и Function Expression для того, чтобы создать `sayHi` в первой строке:
77+
Мы также могли бы использовать Function Expression для объявления `sayHi` в первой строке:
6778

6879
```js
69-
let sayHi = function() {
80+
let sayHi = function() { // (1) создаём
7081
alert( "Привет" );
7182
};
7283

7384
let func = sayHi;
7485
// ...
7586
```
7687

77-
Результат был бы таким же.
88+
Всё будет работать так же.
7889

7990
````smart header="Зачем нужна точка с запятой в конце?"
8091
У вас мог возникнуть вопрос: Почему в Function Expression ставится точка с запятой `;` на конце, а в Function Declaration нет:
@@ -89,14 +100,14 @@ let sayHi = function() {
89100
}*!*;*/!*
90101
```
91102
92-
Ответ прост:
93-
- Нет необходимости в `;` в конце блоков кода и синтаксических конструкций, которые их используют, таких как `if { ... }`, `for { }`, `function f { }` и т.д.
94-
- Function Expression использует внутри себя инструкции присваивания `let sayHi = ...;` как значение. Это не блок кода, а выражение с присваиванием. Таким образом, точка с запятой не относится непосредственно к Function Expression, она лишь завершает инструкцию.
103+
Ответ прост: Function Expression создаётся здесь как `function(...) {...}` внутри выражения присваивания: `let sayHi = …;`. Точку с запятой `;` рекомендуется ставить в конце выражения, она не является частью синтаксиса функции.
104+
105+
Точка с запятой нужна там для более простого присваивания, такого как `let sayHi = 5;`, а также для присваивания функции.
95106
````
96107

97108
## Функции-"колбэки"
98109

99-
Рассмотрим ещё примеры функциональных выражений и передачи функции как значения.
110+
Давайте рассмотрим больше примеров передачи функции в виде значения и использования функциональных выражений.
100111

101112
Давайте напишем функцию `ask(question, yes, no)` с тремя параметрами:
102113

@@ -133,7 +144,7 @@ ask("Вы согласны?", showOk, showCancel);
133144

134145
На практике подобные функции очень полезны. Основное отличие "реальной" функции `ask` от примера выше будет в том, что она использует более сложные способы взаимодействия с пользователем, чем простой вызов `confirm`. В браузерах такие функции обычно отображают красивые диалоговые окна. Но это уже другая история.
135146

136-
**Аргументы функции `ask` ещё называют *функциями-колбэками* или просто *колбэками*.**
147+
**Аргументы `showOk` и `showCancel` функции `ask` называются *функциями-колбэками* или просто *колбэками*.**
137148

138149
Ключевая идея в том, что мы передаём функцию и ожидаем, что она вызовется обратно (от англ. "call back" - обратный вызов) когда-нибудь позже, если это будет необходимо. В нашем случае, `showOk` становится *колбэком* для ответа "yes", а `showCancel` -- для ответа "no".
139150

@@ -164,7 +175,7 @@ ask(
164175
```smart header="Функция - это значение, представляющее \"действие\""
165176
Обычные значения, такие как строки или числа представляют собой *данные*.
166177
167-
Функции, с другой стороны, можно воспринимать как "действия".
178+
Функции, с другой стороны, можно воспринимать как *действия*.
168179
169180
Мы можем передавать их из переменной в переменную и запускать, когда захотим.
170181
```
@@ -174,17 +185,17 @@ ask(
174185

175186
Давайте разберём ключевые отличия Function Declaration от Function Expression.
176187

177-
Во-первых, синтаксис: как определить, что есть что в коде.
188+
Во-первых, синтаксис: как отличить их друг от друга в коде.
178189

179-
- Function Declaration: функция объявляется отдельной конструкцией "function..." в основном потоке кода.
190+
- *Function Declaration*: функция объявляется отдельной конструкцией "function..." в основном потоке кода.
180191

181192
```js
182193
// Function Declaration
183194
function sum(a, b) {
184195
return a + b;
185196
}
186197
```
187-
- Function Expression: функция, созданная внутри другого выражения или синтаксической конструкции. В данном случае функция создаётся в правой части "выражения присваивания" `=`:
198+
- *Function Expression*: функция, созданная внутри другого выражения или синтаксической конструкции. В данном случае функция создаётся в правой части "выражения присваивания" `=`:
188199

189200
```js
190201
// Function Expression
@@ -201,7 +212,7 @@ ask(
201212

202213
С Function Declaration всё иначе.
203214

204-
**Function Declaration можно использовать во всем скрипте (или блоке кода, если функция объявлена в блоке).**
215+
**Function Declaration может быть вызвана раньше, чем она объявлена.**
205216

206217
Другими словами, когда движок JavaScript *готовится* выполнять скрипт или блок кода, прежде всего он ищет в нём Function Declaration и создаёт все такие функции. Можно считать этот процесс "стадией инициализации".
207218

@@ -241,9 +252,9 @@ let sayHi = function(name) { // (*) магии больше нет
241252

242253
**В строгом режиме, когда Function Declaration находится в блоке `{...}`, функция доступна везде внутри блока. Но не снаружи него.**
243254

244-
Для примера давайте представим, что нам нужно создать функцию `welcome()` в зависимости от значения переменной `age`, которое мы получим во время выполнения кода. И затем запланируем использовать её когда-нибудь в будущем.
255+
Для примера давайте представим, что нам нужно объявить функцию `welcome()` в зависимости от значения переменной `age`, которое мы получим во время выполнения кода. И затем запланируем использовать её когда-нибудь в будущем.
245256

246-
Такой код, использующий Function Declaration, работать не будет:
257+
Если мы попробуем использовать Function Declaration, это не заработает так, как задумывалось:
247258

248259
```js run
249260
let age = prompt("Сколько Вам лет?", 18);
@@ -274,7 +285,7 @@ welcome(); // Error: welcome is not defined
274285
Вот ещё один пример:
275286

276287
```js run
277-
let age = 16; // присвоим для примера 16
288+
let age = 16; // возьмём для примера 16
278289
279290
if (age < 18) {
280291
*!*
@@ -308,7 +319,7 @@ welcome(); // Ошибка: welcome is not defined
308319

309320
Верным подходом будет воспользоваться функцией, объявленной при помощи Function Expression, и присвоить значение `welcome` переменной, объявленной снаружи `if`, что обеспечит нам нужную видимость.
310321

311-
Такой код работает, как ожидалось:
322+
Такой код заработает, как ожидалось:
312323

313324
```js run
314325
let age = prompt("Сколько Вам лет?", 18);
@@ -334,7 +345,7 @@ welcome(); // теперь всё в порядке
334345
*/!*
335346
```
336347

337-
Можно упростить этот код ещё сильнее, используя условный оператор `?`:
348+
Или мы могли бы упростить это ещё сильнее, используя условный оператор `?`:
338349

339350
```js run
340351
let age = prompt("Сколько Вам лет?", 18);
@@ -354,17 +365,17 @@ welcome(); // теперь всё в порядке
354365
355366
Также функции вида `function f(…) {…}` чуть более заметны в коде, чем `let f = function(…) {…}`. Function Declaration легче "ловятся глазами".
356367
357-
...Но если Function Declaration нам не подходит по какой-то причине (мы рассмотрели это в примере выше), то можно использовать объявление при помощи Function Expression.
368+
...Но если Function Declaration нам не подходит по какой-то причине, или нам нужно условное объявление (мы рассмотрели это в примере выше), то следует использовать Function Expression.
358369
```
359370

360371
## Итого
361372

362373
- Функции - это значения. Они могут быть присвоены, скопированы или объявлены в любом месте кода.
363-
- Если функция объявлена как отдельная инструкция в основном потоке кода, то это Function Declaration.
364-
- Если функция была создана как часть выражения, то считается, что эта функция объявлена при помощи Function Expression.
374+
- Если функция объявлена как отдельная инструкция в основном потоке кода, то это Function Declaration.
375+
- Если функция была создана как часть выражения, то это “Function Expression.
365376
- Function Declaration обрабатываются перед выполнением блока кода. Они видны во всём блоке.
366-
- Функции, объявленные при помощи Function Expression, создаются, только когда поток выполнения достигает их.
377+
- Функции, объявленные при помощи Function Expression, создаются только когда поток выполнения достигает их.
367378

368-
В большинстве случаев, когда нам нужно создать функцию, предпочтительно использовать Function Declaration, т.к. функция будет видима до своего объявления в коде. Это позволяет более гибко организовывать код и улучшает его читаемость.
379+
В большинстве случаев, когда нам нужно объявить функцию, Function Declaration предпочтительнее, т.к функция будет видна до своего объявления в коде. Это даёт нам больше гибкости в организации кода и, как правило, делает его более читабельным.
369380

370-
Таким образом, мы должны прибегать к объявлению функций при помощи Function Expression в случае, когда синтаксис Function Declaration не подходит для нашей задачи. Мы рассмотрели несколько таких примеров в этой главе, и рассмотрим их ещё больше в будущем.
381+
Исходя из этого, мы должны использовать Function Expression только тогда, когда Function Declaration не подходит для нашей задачи. Мы рассмотрели несколько таких примеров в этой главе, и увидим ещё больше в будущем.

0 commit comments

Comments
 (0)