In-depth understanding of javascript scope series fourth - block scope

previous words

Although function scoping is the most common scoping unit and the most common design method for most javascripts today, other types of scoping units also exist and can even be maintained by using other types of scoping units. Better, cleaner code, like block scoping. With the promotion of ES6, block scope will also be used more and more widely.

let

for (var i= 0; i<10; i++) {
    console.log(i);
}

The above code is familiar loop code, usually just because you want to use the variable i in the context inside the for loop. But in fact i can be accessed in the global scope, thus polluting the entire scope.

for (var i= 0; i<10; i++) {
     console.log(i);
}
console.log(i);//10

ES6 changed this situation with the introduction of the keyword let, which provides an alternative to var for variable declarations. The let keyword can bind a variable to any scope it is in (usually inside {…}), achieving block scope.

{
  let i = 1;  
};
console.log(i);//ReferenceError: i is not defined

Block scope can actually be used in place of an anonymous function that executes immediately. (IIFE)

(function(){
  var i = 1;  
})();
console.log(i);//ReferenceError: i is not defined

If the variable i in the code of the for loop at the beginning of the article is declared with let, the problem of scope pollution will be avoided.

for (let i= 0; i<10; i++) {
     console.log(i);
}
console.log(i);////ReferenceError: i is not defined

The let at the head of the for loop not only binds i to the block of the for loop, it actually rebinds it to each iteration of the loop, making sure to reassign it with the value at the end of the previous loop iteration. (I don't understand this sentence very well)

//与上一段代码等价
{
    let j;
    for (j=0; j<10; j++) {
        let i = j; //每个迭代重新绑定
        console.log( i );
    }
}

cycle

In the code below, the console prints 5 instead of 0 because the closure can only take the last value of any variable in the containing function.

var a = [];
for(var i = 0; i < 5; i++){
    a[i] = function(){
        return i;
    }
}
console.log(a[0]());//5

My understanding is that the reason it outputs 5 is because when the for loop binds the function for each array element, it just binds it, it doesn't get called. iTherefore, the value in the function body is not assigned any value during the compilation phase . It is only during the function call phase that this i will perform the RHS query and then search the scope chain. At this time, the value of i in the global is 5. So no matter which array element is called the function returns 5.

 var a = [];
   for(var i = 0; i < 5; i++){
       a[i] = function(){
           return i;
       }
   }
   console.log(a[0]());//5
   console.log(a[1]());//5
   console.log(a[2]());//5
   console.log(a[3]());//5
   console.log(a[4]());//5

Of course, the value of each loop can be saved in the form of function parameters.

var a = [];
for(var i = 0; i < 5; i++){
    a[i] = (function(j){
        return function(){
            return j; 
        }
    })(i);
    //通过函数传参,并且绑定时通过立即执行函数,把绑定的函数执行了。
    //所以调用时,返回的j就是对应传入的那个i.
}
console.log(a[0]());//0

It is more convenient to use let, because the let loop has a reassignment process, which is equivalent to saving the value of each loop.

var a = [];
for(let i = 0; i < 5; i++){
    a[i] = function(){
        return i;
    }
}
console.log(a[0]());//0

Repeat statement

let does not allow the same variable to be declared repeatedly in the same scope.

{
  let a = 10;
  var a = 1;//SyntaxError: Unexpected identifier
}

promote

Declarations made with let are not hoisted in block scope.

{
  console.log(i);//ReferenceError: i is not defined
  let i = 1;  
};

const

In addition to let, ES6 also introduced const, which can also be used to create block-scoped variables. But its value is fixed (constant). Any subsequent attempt to modify the value will result in an error.

if (true) {
    var a = 2;
    const b = 3; 
    a = 3; 
    b = 4;// TypeError: Assignment to constant variable(常量)
}
console.log( a ); // 3
console.log( b ); // ReferenceError: b is not defined(块作用域变量)

The constant declared by const is also not repeatable declaration like let.

const message = "Goodbye!";
const message = "Goodbye!";//SyntaxError: Identifier 'message' has already been declared

try

A common use of try-catch statements is to create block-level scope, where variables declared are only valid inside the catch.

{
    let a = 2;
    console.log(a); // 2
}
console.log(a); //ReferenceError: a is not defined

In a pre-ES6 environment, a try-catch statement can be used to achieve a similar effect to the code above.

try{
    throw 2;
}catch(a){
    console.log( a ); // 2
}
console.log( a ); //ReferenceError: a is not defined
//或者
try{
    throw undefined;
}catch(a){
    a = 2; //对a进行赋值,仅在catch内部有效。
    console.log( a ); // 2
}
console.log( a ); //ReferenceError: a is not defined

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=325640523&siteId=291194637