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 likevarThat 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.