var,let和闭包

Posted by Alei Blog on July 7, 2018

说明

  • let是ES6的新运算符

重复声明变量

  • var允许
    var a = 1
    var a = 2
    console.log(a)
    // 2
    
  • let不允许
    let b = 1
    let b = 2
    console.log(b)
    // SyntaxError: Identifier 'b' has already been declared
    

作用域

  • var的作用域是函数之内的全局
    if(2 > 1 ){
        var a = 3
    }
    console.log(a)
    //运行,控制台打印 3
    //java语言,类似的代码是错误的代码,a是if语句里面的局部变量,log(a)会报错变量a不存在
    
  • let提供了更精细的块级作用域
    if(2 > 1 ){
        let a = 3
    }
    console.log(a)
    //运行报错 ReferenceError: a is not defined
    
  • for循环中,延迟执行的var陷阱
    for (var i = 0; i < 3; i++) {
        setTimeout(
           function () {
               console.log("使用var,变量值i的值是:"+i)
           }
        )
    }
    //使用var,变量值i的值是:3
    //使用var,变量值i的值是:3
    //使用var,变量值i的值是:3
    
  • for循环中,延迟执行的let表现正常
    for (let i = 0; i < 3; i++) {
        setTimeout(
           function () {
               console.log("使用let,变量值i的值是:"+i)
           }
        )
    }
    //使用let,变量值i的值是:0
    //使用let,变量值i的值是:1
    //使用let,变量值i的值是:2
    

闭包

  • 闭包就是变量和使用变量的函数所形成的环境
  • 使用嵌套闭包来限制var的作用域,避免for循环中延迟执行的陷阱
  • 也就是说,在for循环中,每次用另一个变量(匿名的,假设是j)来接收了var i的当前值。然后用j和function(j)形成闭包
    for (var i = 0; i < 3; i++) {
        (
            function (i) {
                setTimeout(function () {
                    console.log("使用var和闭包,变量i的值是:" + i)
                })
      
            }
        )(i)
    }
    //使用var和闭包,变量i的值是:0
    //使用var和闭包,变量i的值是:1
    //使用var和闭包,变量i的值是:2
    
  • 等价的代码,显式声明
    for (var i = 0; i < 5 ; i++) {
        var j = i
        function f(k){
            setTimeout(
                function () {
                    console.log("使用var和闭包,变量k的值是:"+ k)
                }
            )
        }
        f(j)
    }  
    //使用var和闭包,变量k的值是:0
    //使用var和闭包,变量k的值是:1
    //使用var和闭包,变量k的值是:2