In ES5 we were used to using VAR, and var often caused us some problems, such as variable promotion, repeated naming (and the latter overrides the former), no temporary dead zones, and no block-level scope. ES6’s new let command, const, solves these problems.
let
Below through the code way to answer, variable promotion, repeated naming, temporary dead zone, block level scope, these problems to solve and add functionality to the usual development we get what help.
- There is no variable promotion
console.log(a); // undefined var a = 1; Var a; console.log(a); // undefined a = 1;Copy the code
Such code, should have seen it? That’s called variable promotion. Because of this strange behavior the code is actually very difficult to maintain. So LET solves this problem.
console.log(a);
let a = 1; // a is not defined
Copy the code
Let does not have the same situation as var. If you use let to define a variable without assigning a value, the value will be undefined
- Duplicate declarations are not allowed
It should be common to declare variables repeatedly using var, but let does not allow the same variable to be declared twice in the same scope.
{
var num = 123;
console.log(num); // 123
var num = 456;
console.log(num); // 456
}
{
let num = 123;
console.log(num); // 123
let num = 456; // SyntaxError: Identifier 'num' has already been declared
}
Copy the code
The output should be obvious, but why the curly braces?
Because the V8 engine does something special with let, let can be declared repeatedly in the console without curly braces.
- Temporary dead zone
As long as a block-level scope has a let command, its declared variables are “bound” to the scope, no longer subject to external influence.
var num = 123;
{
num = 456; // ReferenceError: Cannot access 'b' before initialization
let num;
}
Copy the code
What does that mean? The variable is not available until the let command is used to declare it.
There are also some more insidious errors, but they are common in development
function test(x = y, y = 2){
return (x, y);
}
test(); // ReferenceError: Cannot access 'b' before initialization
Copy the code
This is also the benefit of temporary dead zones, to avoid the bad habit of using variables after they have been declared, otherwise an error will be reported.
- Block-level scope
Inner variables may override outer variables.
var num = 123; function fun(){ console.log(num); if(false){ var num = 456; console.log(num); } } fun(); Funcion fun(){var num; console.log(num); if(false) { num = 456; console.log(num); } } var num; num = 123; fun(); // undefinedCopy the code
This code just wants to print the outer num in the function and the self defined num in the if judgment, but it prints undefined, because of the variable promotion and also because there is no block-level scope.
The lack of block-level scope also causes loop variables to leak out as global variables.
for(var i = 0; i < 5; i++){ console.log(i); // 0 1 2 3 4 } console.log(i); / / 5Copy the code
Block-level scope does not affect the benefits of global scope.
{
var a = 1;
let b = 2;
}
console.log(a); // 1
console.log(b); // ReferenceError: b is not definedat <anonymous>:6:13
Copy the code
Why does A print normally but B report an error? Because variables defined by var do not have block-level scope, that is, they can be accessed globally. Only when var is used in functions does the scope exist and does not affect the global. Therefore, function scope is often heard in ES5, but you do not need to worry about using let. As long as braces are wrapped around it, JavaScript thinks it has block-level scope and therefore can avoid affecting the global scope.
var a = []; for (var i = 0; i < 10; i++) { a[i] = function () { console.log(i); }; } a[6](); / / 10Copy the code
Why does a[6]() print 10?
Because I is declared by var, the variable declared by var is global, so it can be accessed globally. Each time through the loop, the variable I changes in value, and the function inside the loop that assigns values to the array is global, so the output value is 10. Maybe some people don’t understand or say what the application scenario is. Let’s look at the following example
Var I for (var I = 1; i < 5; I ++) {setTimeout(() => console.log(I), 1000) // 5 5 5 5 5} i < 5; i++) { setTimeout(() => console.log(i), 1000) // 1 2 3 4 }Copy the code
So there’s a scenario. I want to control how long it takes to print, but why print four fives? There are a lot of things to cover here (closures, promotions, event loops), but let is not the topic today, and I will explain it separately later, because let can solve this problem.
Since the variables declared in let are not globally valid, the current I is valid only in this loop, so each loop is actually a new value, so they don’t interfere with each other. You might also ask how do you know the value of the current loop if it’s a new value every time? This is what the JavaScript engine does internally. For now, it’s just a matter of knowing what to do, and I’ll explain it separately later. After all, there are a lot of knowledge points involved, so don’t get sidetracked.
- Block-level scope declaration functions
function fun(){ console.log('outside') } (function (){ if(false) { function fun(){ console.log('inside') } } fun(); } ()); Funciton (){function fun(){console.log('inside')} if(false){} fun(); // inside }());Copy the code
In ES5, of course, it prints inside. In ES6, it says fun is not a function. Should be all right.
But what does this actually say? Some of you don’t get it, so let me explain. Let’s take a look at this
if(true){
function fun(){}
}
Copy the code
In ES5, functions can only be declared in top-level scopes and function scopes, not block-level scopes.
Later, ES6 introduced block-level scopes and explicitly allowed functions to be declared in block-level scopes. ES6 states that a function declaration statement in a block-level scope behaves like a LET and cannot be referenced outside the block-level scope. However, it needs to be compatible with older code, so appendix B also explains that browsers can behave in their own way without following the above rules. That is
- Allows functions to be declared in block-level scopes
- But at run time it looks like
var
That is, the header that will be promoted to the global scope or function scope. - Function declarations are also promoted to the head of their block-level scope.
Note: The above rules are only applicable to ES6 environments and do not need to be followed in other environments.
Follow the rules above to see how ES6 works in practice
function fun() { console.log('outside') } (function () { var fun = undefined; If (false) {let fun1 = function () {console.log('inside')} } fun(); // fun is not a function }())Copy the code
That is, function declarations are allowed in block-level scopes, but because of block-level scopes and compatibility with older code, fun is not promoted outside the block-level scope, but to the head of the block-level scope.
const
What is const? Const declares a constant. It must be assigned at the same time and the value is immutable.
// const const P = 3.14159; P = 3; // TypeError: Assignment to constant variable. // const num; // SyntaxError: Missing initializer in const declarationCopy the code
Const, like let, has block-level scope and temporary dead zones
// Temporary dead zone console.log(P); // ReferenceError: Cannot access 'P' before initialization const P = 3.14159; // block-level scope {const P = 3.14; } console.log(P); // ReferenceError: P is not definedCopy the code
The essence of const is to keep the memory address to which the variable points unchanged. That is, the value of an attribute in a reference type is mutable and can be added.
const obj = {}; Name = 'obj '; console.log(obj); } obj. Name = '中 国 名 字 : 中 国 名 字 '; console.log(obj); } const arr = [1, 2, 3]; // const arr = [1, 2, 3]; arr.splice(1); console.log(arr); // [1] arr.push(4); console.log(arr); / / [1, 4]Copy the code
- Global (window)
Finally, let’s take a look at the big picture, which is often mentioned above.
The global scope, also known as the top-level object, is the Window object in the browser and the global object in nodeJS. It is often mentioned that variables defined by var are globally accessible. Look at the code
var num = 123;
console.log(window.num); // 123
function fn(){
console.log(123123);
}
window.fn(); // 123123
let num2 = 456;
console.log(window.num2); // undefined
const num3 = 789;
console.log(window.num3); // undefined
class fn{}
window.fn; // undefined
Copy the code
The top-level object is hooked to the global property. What does that mean?
The var command and the function command declare properties of the top-level object. So you can use the window to find the corresponding property. ES6 changes this, but for compatibility purposes, so variables and functions declared by var and function are still attributes of the top-level object, but global variables declared by let, const, and class are not.