Skip to content

Commit d9a1e9b

Browse files
committed
up
1 parent 3de8c80 commit d9a1e9b

11 files changed

+108
-37
lines changed

1-js/5-deeper/2-closure/article.md

Lines changed: 108 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -376,73 +376,143 @@ In the very first chapter about [variables](info:variables), we mentioned three
376376

377377
Here we only talked about `let`. But `const` behaves totally the same way in terms of Lexical Environments.
378378

379-
The `var` is a completely different beast, coming from old times. It is usually not used in modern scripts, but still lurks in the old ones.
379+
The `var` is a very different beast, coming from old times. It's generally not used in modern scripts, but still lurks in the old ones.
380380

381-
**A `var` variable only recognizes function and global Lexical Environments, not blocks.**
381+
If you don't plan meeting such scripts you may even skip this subsection and return if/when this beasts bites
382382

383-
For instance:
383+
From the first sight, `var` behaves similar to `let`:
384384

385-
```js
386-
if (true) {
387-
var test = true; // use "var" instead of "let"
385+
```js run
386+
function sayHi() {
387+
var phrase = "Hello"; // local variable, "var" instead of "let"
388+
389+
alert(phrase); // Hello
388390
}
389391

390-
*!*
391-
alert(test); // true, variable lives after if
392-
*/!*
392+
sayHi();
393+
394+
alert(phrase); // Error, phrase is not defined
393395
```
394396

395-
If we used `let test`, then it wouldn't be visible to `alert`. But `var` variables ignore code blocks, so here we've got a global `test`.
397+
...But let's list the differences.
396398

397-
The same thing for loops:
399+
`var` variables only recognize function and global Lexical Environments, they ignore blocks.
400+
: For instance:
398401

399-
```js
400-
for(var i = 0; i < 10; i++) {
401-
// ...
402-
}
402+
```js
403+
if (true) {
404+
var test = true; // use "var" instead of "let"
405+
}
403406

404-
*!*
405-
alert(i); // 10, visible after loop, global variable
406-
*/!*
407-
```
407+
*!*
408+
alert(test); // true, the variable lives after if
409+
*/!*
410+
```
408411

409-
The only Lexical Environment respected by `var` is function.
412+
If we used `let test`, then it wouldn't be visible to `alert`. But `var` variables ignore code blocks, so here we've got a global `test`.
410413

411-
So here it behaves the same way as `let`:
414+
The same thing for loops:
412415

413-
```js run
414-
function sayHi() {
415-
var phrase = "Hello"; // local variable
416+
```js
417+
for(var i = 0; i < 10; i++) {
418+
// ...
419+
}
416420

417-
alert(phrase); // Hello
418-
}
421+
*!*
422+
alert(i); // 10, "i" is visible after loop, it's a global variable
423+
*/!*
424+
```
419425

420-
sayHi();
426+
As we can see, `var` pierces through `if`, `for` or other code blocks. That's because some time ago, in Javascript blocks had no Lexical Environments. And `var` is a reminiscence of that.
421427

422-
alert(phrase); // Error, phrase is not defined
423-
```
428+
`var` declarations are processed when the function starts (or when the script starts for globals).
429+
: Technically, it means that all `var` variables are defined from the beginning of the function.
424430

425-
HOISTED
431+
So this code:
426432

433+
```js
434+
function sayHi() {
435+
phrase = "Hello";
427436

437+
alert(phrase);
428438

439+
*!*
440+
var phrase;
441+
*/!*
442+
}
443+
```
429444

445+
...Is technically the same as:
430446

447+
```js
448+
function sayHi() {
449+
*!*
450+
var phrase;
451+
*/!*
452+
phrase = "Hello";
453+
454+
alert(phrase);
455+
}
456+
```
431457

458+
...Or even like this (remember, code blocks are ignored):
432459

460+
```js
461+
function sayHi() {
462+
phrase = "Hello";
463+
464+
*!*
465+
if (false) {
466+
var phrase;
467+
}
468+
*/!*
469+
470+
alert(phrase);
471+
}
472+
```
433473

474+
People also call such behavior "hoisting" (raising), because all `var` are "hoisted" (raised) to the top of the function.
434475

476+
**The pitfall is that assignments are not hoisted**.
435477

478+
For instance:
436479

437-
**The `var` variables are "hoisted" to the top of functions.**
480+
```js run
481+
function sayHi() {
482+
alert(phrase);
438483

439-
In other words, a `var` declaration is processed in the beginning of the function (or the whole script for globals).
484+
*!*
485+
var phrase = "Hello";
486+
*/!*
487+
}
488+
489+
sayHi();
490+
```
491+
492+
The line `var phrase = "Hello"` has two actions in it: variable declaration and assignment.
493+
494+
The declaration is hoisted, but the assignment is not. The `alert` works, because the variable is defined from the start of the function. But its value is assigned below, so it shows `undefined`.
495+
496+
The code is essentially the same as:
497+
498+
```js run
499+
function sayHi() {
500+
*!*
501+
var phrase;
502+
*/!*
503+
504+
alert(phrase); // undefined
505+
506+
phrase = "Hello";
507+
}
508+
509+
sayHi();
510+
```
511+
512+
The features described above make using `var` inconvenient most of time. Because we can't create block-local variables. And hoisting just creates more space for errors. So, once again, nowadays, `vars` are used exceptionally rarely. But they exist in old scripts.
440513

441-
It popu
442514

443-
These
444515

445-
So, it is visible outside of blocks, for instance:
446516

447517
## Global object
448518

@@ -455,8 +525,9 @@ As described in the [specification](https://tc39.github.io/ecma262/#sec-lexical-
455525
The key word here is "some". In practice:
456526

457527
- `Array`, `Object`, `alert`, `prompt` and other built built-in functions and variables and Function Decla
458-
459-
**Function Declarations
528+
- let not in
529+
- var is in
530+
- FDs are in
460531

461532

462533

23.8 KB
Loading
57.1 KB
Loading
26.7 KB
Loading
67.2 KB
Loading
15.5 KB
Loading
37.5 KB
Loading
17.5 KB
Loading
42.7 KB
Loading
7.87 KB
Loading

0 commit comments

Comments
 (0)