This commit is contained in:
Ilya Kantor 2017-03-21 17:14:05 +03:00
parent ab9ab64bd5
commit 97c8f22bbb
289 changed files with 195 additions and 172 deletions

View file

@ -605,172 +605,3 @@ This feature of V8 is good to know. If you are debugging with Chrome/Opera, soon
That is not a bug of debugger, but a special feature of V8. Maybe it will be changed sometimes.
You always can check for it by running examples on this page.
```
## The old "var"
In the very first chapter about [variables](info:variables), we mentioned three ways of variable declaration:
1. `let`
2. `const`
3. `var`
`let` and `const` behave exactly the same way in terms of Lexical Environments.
But `var` is a very different beast, that originates from very old times. It's generally not used in modern scripts, but still lurks in the old ones. If you don't plan meeting such scripts you may even skip this subsection or postpone reading it, but then there's a chance that it bites you some time.
From the first sight, `var` behaves similar to `let`. That is, declares a variable:
```js run
function sayHi() {
let phrase = "Hello"; // local variable, "var" instead of "let"
alert(phrase); // Hello
}
sayHi();
alert(phrase); // Error, phrase is not defined
```
...But here are the differences.
`var` variables are either funciton-wide or global, they are visible through blocks.
: For instance:
```js
if (true) {
let test = true; // use "var" instead of "let"
}
*!*
alert(test); // true, the variable lives after if
*/!*
```
If we used `let test` on the 2nd line, then it wouldn't be visible to `alert`. But `var` ignores code blocks, so we've got a global `test`.
The same thing for loops: `var` can not be block or loop-local:
```js
for(let i = 0; i < 10; i++) {
// ...
}
*!*
alert(i); // 10, "i" is visible after loop, it's a global variable
*/!*
```
If a code block in inside a function, then `var` becomes a function-level variable:
```js
function sayHi() {
if (true) {
let phrase = "Hello";
}
alert(phrase); // works
}
sayHi();
alert(phrase); // Error: phrase is not defined
```
As we can see, `var` pierces through `if`, `for` or other code blocks. That's because long time ago in JavaScript blocks had no Lexical Environments. And `var` is a reminiscence of that.
`var` declarations are processed when the function starts (or script starts for globals).
: In other words, `var` variables are defined from the beginning of the function.
So this code:
```js
function sayHi() {
phrase = "Hello";
alert(phrase);
*!*
let phrase;
*/!*
}
```
...Is technically the same as this:
```js
function sayHi() {
*!*
let phrase;
*/!*
phrase = "Hello";
alert(phrase);
}
```
...Or even as this (remember, code blocks are ignored):
```js
function sayHi() {
phrase = "Hello";
*!*
if (false) {
let phrase;
}
*/!*
alert(phrase);
}
```
People also call such behavior "hoisting" (raising), because all `var` are "hoisted" (raised) to the top of the function.
So in the example above, `if (false)` branch never executes, but that doesn't matter. The `var` inside it is processed in the beginning of the function.
**The important thing is that declarations are hoisted, but assignments are not.**
For instance:
```js run
function sayHi() {
alert(phrase);
*!*
let phrase = "Hello";
*/!*
}
sayHi();
```
The line `let phrase = "Hello"` has two actions in it: variable declaration `var` and assignment `=`.
The declaration is processed at the start of function execution (hoisted), but the assignment is not. So the code works essentially like this:
```js run
function sayHi() {
*!*
let phrase; // variable is declared from the top...
*/!*
alert(phrase); // undefined
*!*
phrase = "Hello"; // ...but assigned when the execution reaches this line.
*/!*
}
sayHi();
```
**In other words, all `var` variables exist, but are `undefined` at the beginning of a function.**
They are assigned later as the execution reaches assignments.
In the example above, `alert` runs without an error, because the variable `phrase` exists. But its value is not yet assigned, so it shows `undefined`.
```warn header="Why we should not use `var`"
Special behaviors of described in this section make using `var` inconvenient most of time. First, we can't create block-local variables. And hoisting just creates more space for errors. So, once again, for new scripts `var` is used exceptionally rarely.
```