作用域(for let var)

2017-07-21  本文已影响78人  BubbleM

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补充

console.log(a)
let a = 0
// 报错 ReferenceError: a is not defined
function () {
    let a = 10
    var a = 1
}  // SyntaxError: Unexpected token (
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暂时性死区和块级作用域
上一篇下一篇

猜你喜欢

热点阅读