美文网首页
作用域(for let var)

作用域(for let var)

作者: BubbleM | 来源:发表于2017-07-21 18:05 被阅读78次

    1. for无块级作用域

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

    执行结果:10
    结果分析:由于JS没有块级作用域,所以for中变量i,由于使用var声明的故会被添加到最近的环境中,在这里就是全局环境.
    每一次循环,新的i值就会覆盖旧值.所以全局i保存的是最后一轮循环后的值10.
    由于a[i]的值是一个函数,在函数内部是一个新的作用域,执行a[6]()会现在当前a[6]()的函数作用域内部查找i,找不到便会去父作用域查找,这里它的父作用域即全局作用域.所以输出10

    作用域链如下:
    全局作用域window: a i
      函数a[i]()内部作用域:

    2. let 构造块级作用域

    var a = []
    for (let i = 0; i < 10; i++) {
      a[i] = function () {
        console.log(i)
      }
    }
    a[6]() // 6
    console.log(i) // 报错 ReferenceError: i is not defined
    

    执行结果:6
    结果分析:
    ES6提供新增let命令,其所声明的变量只在let命令所在的代码块内有效.
    for中的变量i用let定义的,当前的i只在本轮循环有效.所以每次的i都是一个新的变量.
    报错的原因是当前是全局作用域无法访问到内部变量

    作用域链如下:
    全局作用域window: a
      块级作用域for: i
        函数a[i]()内部作用域:

    3. 关于let补充

    • 不存在变量提升
      let不像var会发生"变量提升"现象.所以,变量一定要在声明后使用.如果在之前使用typeof也会报错
    console.log(a)
    let a = 0
    // 报错 ReferenceError: a is not defined
    
    • 不允许重复声明
      let不允许在相同作用域内重复声明同一个变量
    function () {
        let a = 10
        var a = 1
    }  // SyntaxError: Unexpected token (
    
    • 暂时性死区
      只要块级作用域中存在let命令,它所声明的变量就绑定这个区域,不再受外部的影响.
    var tmp = 123
      if (true) {
        tmp = 'abc'
        let tmp
      }
    // ReferenceError: tmp is not defined
    

    报错原因:
    存在全局变量tmp,但是块级作用域内let又声明了一个局部变量tmp,导致后者绑定这个块级作用域,所以在let声明变量前,对tmp赋值会报错.

    ES6规定:如果区块中存在let和const命令,则这个区块对这些命令声明的变量从一开始就形成封闭作用域.只要在声明之前使用这些变量,就会报错.
    在代码块内,使用let命令声明变量之前,该变量都是不可用的.这种语法上称"暂时性死区Temporal dead zone,简称TDZ"


    有些死区比较隐蔽,不容易被发现

    function bar(x = y,y = 2) {
        return [x, y]
    }
    bar(); // SyntaxError: Invalid or unexpected token
    

    报错原因:参数x默认值等于另一个参数y,而此时y还没有声明,属于"死区" 如果修改为 function bar(x = 2,y = x)就不会报错


    for循环的计数器,很适合用let命令

    思考题一

    var Test = {
      foo: 'test',
      func: function () {
        var self = this;
        console.log(this.foo); // test
        console.log(self.foo); // test
        (function () {
          console.log(this.foo); // undefined
          console.log(self.foo); // test
        })();
      }
    }
    Test.func();
    
    function test() {
      for(let i = 0; i < 5;i++) {
        setTimeout(function () {
          console.log(i); // 0,1,2,3,4
        },1000);
      }
    }
    test();
    
    function test() {
      for(var i = 0; i < 5;i++) {
        setTimeout(function () {
          console.log(i); // 5,5,5,5,5
        },1000);
      }
    }
    test();
    

    思考题二

    1. let暂时性死区和块级作用域

    相关文章

      网友评论

          本文标题:作用域(for let var)

          本文链接:https://www.haomeiwen.com/subject/szmekxtx.html