一个小伙

let反思--块作用域

2018.09.25

由 let 块作用域,反思自己的无知…

Demo

我们先来一个例子

for (var i = 0; i < 5; i++) {
  setTimeout(function() {
    console.log(i);
  }, 100 * i);
}

// 5
// 间隔 100ms 依次输出 5 个 5
for (let i = 0; i < 5; i++) {
  setTimeout(function() {
    console.log(i);
  }, 100 * i);
}

// 0
// 1
// 2
// 3
// 4
// 间隔 100ms 依次输出 0-4

是不是发现二者的不同之处了,是的, 声明变量不同,letvar

当 let 声明出现在循环体里时拥有完全不同的行为。 不仅是在循环里引入了一个新的变量环境,而是针对 每次迭代都会创建这样一个新作用域。 这就是我们在使用立即执行的函数表达式时做的事,所以在 setTimeout 例子里我们仅使用 let 声明就可以了。

块级作用域

可以通过一个简单的案例查看到明显区别:

function demo() {
  let n = 5;
  if (true) {
    let n = 10;
  }
  console.log(n); // 5
}
function demo() {
  var n = 5;
  if (true) {
    var n = 10;
  }
  console.log(n); // 10
}

let 允许你声明一个作用域被限制在块级中的变量、语句或者表达式。与 var 关键字不同的是,var 声明的变量只能是全局或者整个函数块的。

let与var的不同当然不止这一点,比如重定义等,更多可查看 let-MDN

More

题外话,如果案例不使用 let 呢? 之前 js 循环延时踩坑  中也提到过。当然,原理还是划分作用域。

如果把 Demo 中的 let 案例转化为 es5  就会发现其中的大不同: 

// es6
for (let i = 0; i < 5; i++) {
  setTimeout(() => {
    console.log(i);
  }, 100 * i);
}
// es5
var _loop = function _loop(i) {
  setTimeout(function() {
    console.log(i);
  }, 100 * i);
};

for (var i = 0; i < 5; i++) {
  _loop(i);
}