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/06-advanced-functions/03-closure/article.md
+22-25
Original file line number
Diff line number
Diff line change
@@ -143,9 +143,9 @@ So, during the function call we have two Lexical Environments: the inner one (fo
143
143
It has a single property: `name`, the function argument. We called `say("John")`, so the value of `name` is `"John"`.
144
144
- The outer Lexical Environment is the global Lexical Environment.
145
145
146
-
It has `phrase` and the function itself.
146
+
It has `phrase`variable and the function itself.
147
147
148
-
The inner Lexical Environment has a reference to the outer one.
148
+
The inner Lexical Environment has a reference to the `outer` one.
149
149
150
150
**When the code wants to access a variable -- the inner Lexical Environment is searched first, then the outer one, then the more outer one and so on until the global one.**
151
151
@@ -160,9 +160,9 @@ Let's see how the search proceeds in our example:
160
160
161
161
Now we can give the answer to the first question from the beginning of the chapter.
162
162
163
-
**A function gets outer variables as they are now; it uses the most recent values.**
163
+
**A function gets outer variables as they are now, it uses the most recent values.**
164
164
165
-
That's because of the described mechanism. Old variable values are not saved anywhere. When a function wants them, it takes the current values from its own or an outer Lexical Environment.
165
+
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.
Hopefully, the situation with outer variables is clear now. For most situations such understanding is enough. There are few details in the specification that we omitted for brevity. So in the next section we cover even more details, not to miss anything.
312
+
Hopefully, the situation with outer variables is clear now. For most situations such understanding is enough. There are few details in the specification that we omitted for brevity. So in the next section we cover even more details.
313
313
314
314
## Environments in detail
315
315
@@ -323,21 +323,23 @@ Please note the additional `[[Environment]]` property is covered here. We didn't
323
323
324
324
At that starting moment there is only `makeCounter` function, because it's a Function Declaration. It did not run yet.
325
325
326
-
**All functions "on birth" receive a hidden property `[[Environment]]` with a reference to the Lexical Environment of their creation.** We didn't talk about it yet, but that's how the function knows where it was made.
326
+
**All functions "on birth" receive a hidden property `[[Environment]]` with a reference to the Lexical Environment of their creation.**
327
+
328
+
We didn't talk about it yet, that's how the function knows where it was made.
327
329
328
330
Here, `makeCounter` is created in the global Lexical Environment, so `[[Environment]]` keeps a reference to it.
329
331
330
332
In other words, a function is "imprinted" with a reference to the Lexical Environment where it was born. And `[[Environment]]` is the hidden function property that has that reference.
331
333
332
-
2. The code runs on, the new global variable `counter` is declared and for its value `makeCounter()`is called. Here's a snapshot of the moment when the execution is on the first line inside `makeCounter()`:
334
+
2. The code runs on, the new global variable `counter` is declared and gets the result of `makeCounter()`call. Here's a snapshot of the moment when the execution is on the first line inside `makeCounter()`:
333
335
334
336

335
337
336
338
At the moment of the call of `makeCounter()`, the Lexical Environment is created, to hold its variables and arguments.
337
339
338
340
As all Lexical Environments, it stores two things:
339
341
1. An Environment Record with local variables. In our case `count` is the only local variable (appearing when the line with `let count` is executed).
340
-
2. The outer lexical reference, which is set to `[[Environment]]` of the function. Here `[[Environment]]` of `makeCounter` references the global Lexical Environment.
342
+
2. The outer lexical reference, which is set to the value of `[[Environment]]` of the function. Here `[[Environment]]` of `makeCounter` references the global Lexical Environment.
341
343
342
344
So, now we have two Lexical Environments: the first one is global, the second one is for the current `makeCounter` call, with the outer reference to global.
343
345
@@ -357,13 +359,11 @@ Please note the additional `[[Environment]]` property is covered here. We didn't
357
359
358
360
That function has only one line: `return count++`, that will be executed when we run it.
359
361
360
-
5. When the `counter()` is called, an "empty" Lexical Environment is created for it. Ithas no local variables by itself. But the `[[Environment]]` of `counter` is used as the outer reference for it, so it has access to the variables of the former `makeCounter()` call where it was created:
362
+
5. When `counter()` is called, a new Lexical Environment is created for the call. It's empty, as `counter`has no local variables by itself. But the `[[Environment]]` of `counter` is used as the `outer` reference for it, that provides has access to the variables of the former `makeCounter()` call where it was created:
361
363
362
364

363
365
364
-
Now if it accesses a variable, it first searches its own Lexical Environment (empty), then the Lexical Environment of the former `makeCounter()` call, then the global one.
365
-
366
-
When it looks for `count`, it finds it among the variables `makeCounter`, in the nearest outer Lexical Environment.
366
+
Now when the call looks for `count` variable, it first searches its own Lexical Environment (empty), then the Lexical Environment of the outer `makeCounter()` call, where finds it.
367
367
368
368
Please note how memory management works here. Although `makeCounter()` call finished some time ago, its Lexical Environment was retained in memory, because there's a nested function with `[[Environment]]` referencing it.
369
369
@@ -373,13 +373,11 @@ Please note the additional `[[Environment]]` property is covered here. We didn't
373
373
374
374

375
375
376
-
So we return to the previous step with the only change -- the new value of `count`. The following calls all do the same.
377
-
378
376
7. Next `counter()` invocations do the same.
379
377
380
378
The answer to the second question from the beginning of the chapter should now be obvious.
381
379
382
-
The `work()` function in the code below uses the`name` from the place of its origin through the outer lexical environment reference:
380
+
The `work()` function in the code below gets`name` from the place of its origin through the outer lexical environment reference:
383
381
384
382

385
383
@@ -430,7 +428,7 @@ For instance, after `if` finishes, the `alert` below won't see the `user`, hence
430
428
431
429
### For, while
432
430
433
-
For a loop, every iteration has a separate Lexical Environment. If a variable is declared in `for`, then it's also local to that Lexical Environment:
431
+
For a loop, every iteration has a separate Lexical Environment. If a variable is declared in `for(let ...)`, then it's also in there:
434
432
435
433
```js run
436
434
for (let i =0; i <10; i++) {
@@ -441,7 +439,7 @@ for (let i = 0; i < 10; i++) {
441
439
alert(i); // Error, no such variable
442
440
```
443
441
444
-
Please note: `let i` is visually outside of `{...}`. The `for` construct is somewhat special here: each iteration of the loop has its own Lexical Environment with the current `i` in it.
442
+
Please note: `let i` is visually outside of `{...}`. The `for` construct is special here: each iteration of the loop has its own Lexical Environment with the current `i` in it.
445
443
446
444
Again, similarly to `if`, after the loop `i` is not visible.
447
445
@@ -537,7 +535,7 @@ There exist other ways besides parentheses to tell JavaScript that we mean a Fun
537
535
}();
538
536
```
539
537
540
-
In all the above cases we declare a Function Expression and run it immediately.
538
+
In all the above cases we declare a Function Expression and run it immediately. Let's note again: nowadays there's no reason to write such code.
541
539
542
540
## Garbage collection
543
541
@@ -554,7 +552,7 @@ f();
554
552
555
553
Here two values are technically the properties of the Lexical Environment. But after `f()` finishes that Lexical Environment becomes unreachable, so it's deleted from the memory.
556
554
557
-
...But if there's a nested function that is still reachable after the end of `f`, then its `[[Environment]]`reference keeps the outer lexical environment alive as well:
555
+
...But if there's a nested function that is still reachable after the end of `f`, then it has `[[Environment]]`property that references the outer lexical environment, so it's also reachable and alive:
558
556
559
557
```js
560
558
functionf() {
@@ -570,7 +568,7 @@ function f() {
570
568
let g =f(); // g is reachable, and keeps the outer lexical environment in memory
571
569
```
572
570
573
-
Please note that if `f()` is called many times, and resulting functions are saved, then the corresponding Lexical Environment objects will also be retained in memory. All 3 of them in the code below:
571
+
Please note that if `f()` is called many times, and resulting functions are saved, then all corresponding Lexical Environment objects will also be retained in memory. All 3 of them in the code below:
574
572
575
573
```js
576
574
functionf() {
@@ -579,9 +577,8 @@ function f() {
579
577
returnfunction() { alert(value); };
580
578
}
581
579
582
-
// 3 functions in array, every one of them links to Lexical Environment (LE for short)
580
+
// 3 functions in array, every one of them links to Lexical Environment
583
581
// from the corresponding f() run
584
-
// LE LE LE
585
582
let arr = [f(), f(), f()];
586
583
```
587
584
@@ -608,7 +605,7 @@ g = null; // ...and now the memory is cleaned up
608
605
609
606
As we've seen, in theory while a function is alive, all outer variables are also retained.
610
607
611
-
But in practice, JavaScript engines try to optimize that. They analyze variable usage and if it's easy to see that an outer variable is not used -- it is removed.
608
+
But in practice, JavaScript engines try to optimize that. They analyze variable usage and if it's obvious from the code that an outer variable is not used -- it is removed.
612
609
613
610
**An important side effect in V8 (Chrome, Opera) is that such variable will become unavailable in debugging.**
614
611
@@ -621,7 +618,7 @@ function f() {
621
618
let value =Math.random();
622
619
623
620
functiong() {
624
-
debugger; // in console: type alert(value); No such variable!
621
+
debugger; // in console: type alert(value); No such variable!
625
622
}
626
623
627
624
return g;
@@ -642,7 +639,7 @@ function f() {
642
639
let value ="the closest value";
643
640
644
641
functiong() {
645
-
debugger; // in console: type alert(value); Surprise!
642
+
debugger; // in console: type alert(value); Surprise!
Copy file name to clipboardExpand all lines: 1-js/06-advanced-functions/05-global-object/article.md
+8-7
Original file line number
Diff line number
Diff line change
@@ -1,32 +1,33 @@
1
1
2
2
# Global object
3
3
4
-
The global object provides variables and functions that are available anywhere. Mostly, the ones that are built into the language or the environment.
4
+
The global object provides variables and functions that are available anywhere. By default, those that are built into the language or the environment.
5
5
6
6
In a browser it is named `window`, for Node.js it is `global`, for other environments it may have another name.
7
7
8
8
Recently, `globalThis` was added to the language, as a standartized name for a global object, that should be supported across all environments. In some browsers, namely non-Chromium Edge, `globalThis` is not yet supported, but can be easily polyfilled.
9
9
10
+
We'll use `window` here, assuming that our environment is a browser. If your script may run in other environments, it's better to use `globalThis` instead.
11
+
10
12
All properties of the global object can be accessed directly:
11
13
12
14
```js run
13
15
alert("Hello");
14
-
15
-
// the same as
16
+
// is the same as
16
17
window.alert("Hello");
17
18
```
18
19
19
-
In a browser, global functions and variables declared with `var` become the property of the global object:
20
+
In a browser, global functions and variables declared with `var`(not `let/const`!) become the property of the global object:
20
21
21
22
```js run untrusted refresh
22
23
var gVar =5;
23
24
24
25
alert(window.gVar); // 5 (became a property of the global object)
25
26
```
26
27
27
-
Please don't rely on that! This behavior exists for compatibility reasons. Modern scripts use JavaScript modules where such thing doesn't happen. We'll cover them later in the chapter [](info:modules).
28
+
Please don't rely on that! This behavior exists for compatibility reasons. Modern scripts use [JavaScript modules](info:modules) where such thing doesn't happen.
28
29
29
-
Also, more modern variable declarations `let`and `const` do not exhibit such behavior at all:
30
+
If we used `let`instead, such thing wouldn't happen:
30
31
31
32
```js run untrusted refresh
32
33
let gLet =5;
@@ -52,7 +53,7 @@ alert(currentUser.name); // John
52
53
alert(window.currentUser.name); // John
53
54
```
54
55
55
-
That said, using global variables is generally discouraged. There should be as few global variables as possible. The code design where a function gets "input" variables and produces certain "outcome" is clearer, less prone to errors and easier to test.
56
+
That said, using global variables is generally discouraged. There should be as few global variables as possible. The code design where a function gets "input" variables and produces certain "outcome" is clearer, less prone to errors and easier to test than if it uses outer or global variables.
Copy file name to clipboardExpand all lines: 1-js/06-advanced-functions/06-function-object/article.md
+10-10
Original file line number
Diff line number
Diff line change
@@ -1,7 +1,7 @@
1
1
2
2
# Function object, NFE
3
3
4
-
As we already know, functions in JavaScript are values.
4
+
As we already know, a function in JavaScript is a value.
5
5
6
6
Every value in JavaScript has a type. What type is a function?
7
7
@@ -12,7 +12,7 @@ A good way to imagine functions is as callable "action objects". We can not only
12
12
13
13
## The "name" property
14
14
15
-
Function objects contain a few useable properties.
15
+
Function objects contain some useable properties.
16
16
17
17
For instance, a function's name is accessible as the "name" property:
18
18
@@ -24,14 +24,14 @@ function sayHi() {
24
24
alert(sayHi.name); // sayHi
25
25
```
26
26
27
-
What's more funny, the name-assigning logic is smart. It also assigns the correct name to functions that are used in assignments:
27
+
What's kind of funny, the name-assigning logic is smart. It also assigns the correct name to a function even it's created without one, and then immediately assigned:
28
28
29
29
```js run
30
30
letsayHi=function() {
31
31
alert("Hi");
32
-
}
32
+
};
33
33
34
-
alert(sayHi.name); // sayHi (works!)
34
+
alert(sayHi.name); // sayHi (there's a name!)
35
35
```
36
36
37
37
It also works if the assignment is done via a default value:
@@ -93,7 +93,7 @@ alert(many.length); // 2
93
93
94
94
Here we can see that rest parameters are not counted.
95
95
96
-
The `length` property is sometimes used for introspection in functions that operate on other functions.
96
+
The `length` property is sometimes used for [introspection](https://en.wikipedia.org/wiki/Type_introspection) in functions that operate on other functions.
97
97
98
98
For instance, in the code below the `ask` function accepts a `question` to ask and an arbitrary number of `handler` functions to call.
99
99
@@ -102,9 +102,9 @@ Once a user provides their answer, the function calls the handlers. We can pass
102
102
- A zero-argument function, which is only called when the user gives a positive answer.
103
103
- A function with arguments, which is called in either case and returns an answer.
104
104
105
-
The idea is that we have a simple, no-arguments handler syntax for positive cases (most frequent variant), but are able to provide universal handlers as well.
105
+
To call `handler` the right way, we examine the `handler.length` property.
106
106
107
-
To call `handlers` the right way, we examine the `length` property:
107
+
The idea is that we have a simple, no-arguments handler syntax for positive cases (most frequent variant), but are able to support universal handlers as well:
108
108
109
109
```js run
110
110
functionask(question, ...handlers) {
@@ -241,7 +241,7 @@ let sayHi = function *!*func*/!*(who) {
241
241
sayHi("John"); // Hello, John
242
242
```
243
243
244
-
There are two special things about the name `func`:
244
+
There are two special things about the name `func`, that are the reasons for it:
245
245
246
246
1. It allows the function to reference itself internally.
247
247
2. It is not visible outside of the function.
@@ -347,6 +347,6 @@ If the function is declared as a Function Expression (not in the main code flow)
347
347
348
348
Also, functions may carry additional properties. Many well-known JavaScript libraries make great use of this feature.
349
349
350
-
They create a "main" function and attach many other "helper" functions to it. For instance, the [jquery](https://jquery.com) library creates a function named `$`. The [lodash](https://lodash.com) library creates a function `_`. And then adds `_.clone`, `_.keyBy` and other properties to (see the [docs](https://lodash.com/docs) when you want learn more about them). Actually, they do it to lessen their pollution of the global space, so that a single library gives only one global variable. That reduces the possibility of naming conflicts.
350
+
They create a "main" function and attach many other "helper" functions to it. For instance, the [jQuery](https://jquery.com) library creates a function named `$`. The [lodash](https://lodash.com) library creates a function `_`. And then adds `_.clone`, `_.keyBy` and other properties to (see the [docs](https://lodash.com/docs) when you want learn more about them). Actually, they do it to lessen their pollution of the global space, so that a single library gives only one global variable. That reduces the possibility of naming conflicts.
351
351
352
352
So, a function can do a useful job by itself and also carry a bunch of other functionality in properties.
Copy file name to clipboardExpand all lines: 1-js/06-advanced-functions/07-new-function/article.md
+6-5
Original file line number
Diff line number
Diff line change
@@ -46,14 +46,13 @@ It is used in very specific cases, like when we receive code from a server, or t
46
46
47
47
## Closure
48
48
49
-
Usually, a function remembers where it was born in the special property `[[Environment]]`. It references the Lexical Environment from where it's created.
49
+
Usually, a function remembers where it was born in the special property `[[Environment]]`. It references the Lexical Environment from where it's created (we covered that in the chapter <info:closure>).
50
50
51
-
But when a function is created using `new Function`, its `[[Environment]]`references not the current Lexical Environment, but instead the global one.
51
+
But when a function is created using `new Function`, its `[[Environment]]`is set to reference not the current Lexical Environment, but the global one.
52
52
53
53
So, such function doesn't have access to outer variables, only to the global ones.
54
54
55
55
```js run
56
-
57
56
functiongetFunc() {
58
57
let value ="test";
59
58
@@ -99,6 +98,8 @@ So if `new Function` had access to outer variables, it would be unable to find r
99
98
100
99
**If `new Function` had access to outer variables, it would have problems with minifiers.**
101
100
101
+
Besides, such code would be architecturally bad and prone to errors.
102
+
102
103
To pass something to a function, created as `new Function`, we should use its arguments.
103
104
104
105
## Summary
@@ -111,12 +112,12 @@ let func = new Function ([arg1, arg2, ...argN], functionBody);
111
112
112
113
For historical reasons, arguments can also be given as a comma-separated list.
113
114
114
-
These three lines mean the same:
115
+
These three declarations mean the same:
115
116
116
117
```js
117
118
newFunction('a', 'b', 'return a + b'); // basic syntax
118
119
newFunction('a,b', 'return a + b'); // comma-separated
119
120
newFunction('a , b', 'return a + b'); // comma-separated with spaces
120
121
```
121
122
122
-
Functions created with `new Function`, have `[[Environment]]` referencing the global Lexical Environment, not the outer one. Hence, they cannot use outer variables. But that's actually good, because it saves us from errors. Passing parameters explicitly is a much better method architecturally and causes no problems with minifiers.
123
+
Functions created with `new Function`, have `[[Environment]]` referencing the global Lexical Environment, not the outer one. Hence, they cannot use outer variables. But that's actually good, because it insures us from errors. Passing parameters explicitly is a much better method architecturally and causes no problems with minifiers.
0 commit comments