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
A function gets outer variables as they are now, it uses the most recent values.
3
+
Функція отримує зовнішні змінні такими, якими вони є зараз, тобто вона використовує останні значення.
4
4
5
-
Old variable values are not saved anywhere. When a function wants a variable, it takes the current value from its own Lexical Environment or the outer one.
5
+
Старі значення змінних ніде не зберігаються. Коли функція потребує змінної, вона бере поточне значення зі свого власного або зовнішнього лексичного середовища.
Copy file name to clipboardExpand all lines: 1-js/06-advanced-functions/03-closure/1-closure-latest-changes/task.md
+8-8Lines changed: 8 additions & 8 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -2,22 +2,22 @@ importance: 5
2
2
3
3
---
4
4
5
-
# Does a function pickup latest changes?
5
+
# Чи побачить функція останні зміни?
6
6
7
-
The function sayHi uses an external variable name. When the function runs, which value is it going to use?
7
+
Функція `sayHi` використовує зовнішню змінну. Яке значення буде використано під час виконання функції?
8
8
9
9
```js
10
-
let name ="John";
10
+
let name ="Іван";
11
11
12
12
functionsayHi() {
13
-
alert("Hi, "+ name);
13
+
alert("Привіт, "+ name);
14
14
}
15
15
16
-
name ="Pete";
16
+
name ="Петро";
17
17
18
-
sayHi(); //what will it show: "John" or "Pete"?
18
+
sayHi(); //що вона покаже "Іван" чи "Петро"?
19
19
```
20
20
21
-
Such situations are common both in browser and server-side development. A function may be scheduled to execute later than it is created, for instance after a user action or a network request.
21
+
Такі ситуації поширені як у браузері, так і в серверній розробці. Функцію можна запланувати на виконання пізніше, ніж вона створена, наприклад, після дії користувача або запиту мережі.
22
22
23
-
So, the question is: does it pick up the latest changes?
23
+
Отже, виникає питання: чи побачить функція останні зміни?
Let's examine what exactly happens inside `makeArmy`, and the solution will become obvious.
2
+
Давайте розберемося, що саме відбувається всередині функції `makeArmy`, і рішення стане очевидним.
3
3
4
-
1.It creates an empty array`shooters`:
4
+
1.Функція створює порожній масив`shooters`:
5
5
6
6
```js
7
7
let shooters = [];
8
8
```
9
-
2.Fills it with functions via `shooters.push(function)`in the loop.
9
+
2.Наповнює його функціями у циклі через `shooters.push(function)`.
10
10
11
-
Every element is a function, so the resulting array looks like this:
11
+
Кожен елемент є функцією, тому отриманий масив виглядає так:
12
12
13
13
```js no-beautify
14
14
shooters = [
@@ -25,40 +25,40 @@ Let's examine what exactly happens inside `makeArmy`, and the solution will beco
25
25
];
26
26
```
27
27
28
-
3.The array is returned from the function.
28
+
3.Функція повертає масив.
29
29
30
-
Then, later, the call to any member, e.g. `army[5]()` will get the element `army[5]` from the array (which is a function) and calls it.
30
+
Потім, виклик будь-якого елемента масиву, наприклад`army[5]()`отримає елемент `army[5]`з масиву (який є функцією) і викликає її.
31
31
32
-
Now why do all such functions show the same value, `10`?
32
+
Чому всі функції показують однакове значення, `10`?
33
33
34
-
That's because there's no local variable `i` inside `shooter` functions. When such a function is called, it takes `i` from its outer lexical environment.
34
+
Зверніть увагу, що всередині функцій `shooter` немає локальної змінної `i`. Коли така функція викликається, вона приймає`i`зі свого зовнішнього лексичного середовища.
35
35
36
-
Then, what will be the value of `i`?
36
+
Тоді яке буде значення`i`?
37
37
38
-
If we look at the source:
38
+
Якщо ми подивимося на код:
39
39
40
40
```js
41
41
function makeArmy() {
42
42
...
43
43
let i = 0;
44
44
while (i < 10) {
45
-
letshooter=function() { //shooter function
46
-
alert( i ); //should show its number
45
+
let shooter = function() { // функція shooter
46
+
alert( i ); // має показати свій номер
47
47
};
48
-
shooters.push(shooter); //add function to the array
48
+
shooters.push(shooter); // додати функцію до масиву
49
49
i++;
50
50
}
51
51
...
52
52
}
53
53
```
54
54
55
-
We can see that all`shooter`functions are created in the lexical environment of`makeArmy()`function. But when `army[5]()` is called, `makeArmy` has already finished its job, and the final value of `i` is `10` (`while` stops at `i=10`).
55
+
Ми бачимо що усі функції`shooter`створені в лексичному середовищі функції `makeArmy()`. Але коли ми викликаємо `army[5]()`, функція `makeArmy`вже закінчила свою роботу, і остаточне значення `i`це`10` (цикл `while`зупиняється на`i=10`).
56
56
57
-
As the result, all `shooter` functions get the same value from the outer lexical environment and that is, the last value, `i=10`.
57
+
В результаті всі функції`shooter`отримують однакове значення із зовнішнього лексичного середовища, тобто останнє значення, `i=10`.
58
58
59
59

60
60
61
-
As you can see above, on each iteration of a `while {...}` block, a new lexical environment is created. So, to fix this, we can copy the value of `i`into a variable within the `while {...}` block, like this:
61
+
Як ви можете бачити вище, на кожній ітерації циклу `while {...}`, створюється нове лексичне середовище. Отже, щоб виправити це, ми можемо скопіювати значення `i`у змінну всередині блоку `while {...}`, ось так:
62
62
63
63
```js run
64
64
function makeArmy() {
@@ -69,8 +69,8 @@ Let's examine what exactly happens inside `makeArmy`, and the solution will beco
69
69
*!*
70
70
let j = i;
71
71
*/!*
72
-
letshooter=function() { //shooter function
73
-
alert( *!*j*/!* ); //should show its number
72
+
let shooter = function() { // функція shooter
73
+
alert( *!*j*/!* ); // має показати свій номер
74
74
};
75
75
shooters.push(shooter);
76
76
i++;
@@ -81,18 +81,18 @@ Let's examine what exactly happens inside `makeArmy`, and the solution will beco
81
81
82
82
let army = makeArmy();
83
83
84
-
//Now the code works correctly
84
+
// Тепер код працює правильно
85
85
army[0](); // 0
86
86
army[5](); // 5
87
87
```
88
88
89
-
Here`let j = i`declares an "iteration-local" variable `j`and copies `i` into it. Primitives are copied "by value", so we actually get an independent copy of `i`, belonging to the current loop iteration.
89
+
Тут`let j = i`оголошує локальну змінну `j`та копіює до неї номер ітерації зі змінної `i`. Примітиви копіюються "за значенням", тому ми фактично отримуємо незалежну копію `i`, що належить до поточної ітерації циклу.
90
90
91
-
The shooters work correctly, because the value of `i`now lives a little bit closer. Not in`makeArmy()` Lexical Environment, but in the Lexical Environment that corresponds to the current loop iteration:
91
+
Функції тепер працюють правильно, тому що змінна `i`"живе" трохи ближче. Не в лексичному середовищі виклику`makeArmy()`, але в лексичному середовищі, яке відповідає поточній ітерації циклу:
92
92
93
93

94
94
95
-
Such a problem could also be avoided if we used `for`in the beginning, like this:
95
+
Такої проблеми також можна було б уникнути, якби ми використали цикл `for`з самого початку, ось так:
96
96
97
97
```js run demo
98
98
function makeArmy() {
@@ -102,8 +102,8 @@ Let's examine what exactly happens inside `makeArmy`, and the solution will beco
102
102
*!*
103
103
for(let i = 0; i < 10; i++) {
104
104
*/!*
105
-
letshooter=function() { //shooter function
106
-
alert( i ); //should show its number
105
+
let shooter = function() { // функція shooter
106
+
alert( i ); // має показати свій номер
107
107
};
108
108
shooters.push(shooter);
109
109
}
@@ -117,13 +117,13 @@ Let's examine what exactly happens inside `makeArmy`, and the solution will beco
117
117
army[5](); // 5
118
118
```
119
119
120
-
That's essentially the same, because `for`on each iteration generates a new lexical environment, with its own variable `i`. So`shooter`generated in every iteration references its own `i`, from that very iteration.
120
+
Це, по суті, те саме, тому що `for`на кожній ітерації створює нове лексичне середовище зі своєю змінною `i`. Тому`shooter`згенерований на кожній ітерації бере посилання на змінну `i`, з тієї самої ітерації.
121
121
122
122

123
123
124
-
Now, as you've put so much effort into reading this, and the final recipe is so simple - just use`for`, you may wonder -- was it worth that?
124
+
Тепер, коли ви доклали так багато зусиль, щоб прочитати це, остаточний рецепт такий простий -- використовуйте цикл`for`, ви можете задатися питанням --чи було воно того варте?
125
125
126
-
Well, if you could easily answer the question, you wouldn't read the solution. So, hopefully this task must have helped you to understand things a bit better.
126
+
Ну, якби ви могли легко відповісти на запитання, ви б не читали рішення. Тож, сподіваюся, це завдання допомогло вам трохи краще зрозуміти як все працює.
127
127
128
-
Besides, there are indeed cases when one prefers`while`to`for`, and other scenarios, where such problems are real.
128
+
Крім того, на практиці бувають випадки, коли віддають перевагу`while`замість`for`, та інші сценарії, де такі проблеми є реальними.
The`work()`function in the code below gets `name`from the place of its origin through the outer lexical environment reference:
3
+
Функція`work()`в коді нижче отримує `name`від місця його походження через посилання на зовнішнє лексичне середовище:
4
4
5
5

6
6
7
-
So, the result is `"Pete"` here.
7
+
Отже, відповіддю буде `"Петро"`.
8
8
9
-
But if there were no `let name`in`makeWorker()`, then the search would go outside and take the global variable as we can see from the chain above. In that case the result would be `"John"`.
9
+
Але якби не було `let name`у`makeWorker()`, тоді пошук вийшов би за межі лексичного середовища та взяв би глобальну змінну, як ми бачимо з ланцюжка вище. В такому випадку відповідь була б `"Іван"`.
0 commit comments