除 JavaScript 外的很多编程语言都支持块作用域,但是 JavaScript 开发者对此并不是那么熟悉,尽管之前的标准中已经隐式的涵盖了这块内容
for(var i=0; i<10; i++) { console.log(i); }
我们把 var 写在 for 里面,通常是想在 for 循环内部的上下文使用 i,但是忽略了 i 会绑定在外部作用域的事实,污染到整个函数作用域中,这就是块作用域的用处。
for(let i=0; i<10; i++) { console.log(i); }
try/catch
之前非常少有人注意到 try/catch 的 catch 分包会创建一个块作用域,其中声明的变量仅在 catch 内部有效
try { undefined(); // 执行一个非法操作来强制制造一个异常 } catch(err) { console.log(err); // 能够正常运行 } console.log(err); // ReferenceError: err not defined
err 仅存在 catch 分句内部
let
ES6 改变了现状,引入了新的 let 关键字,提供了除 var 以外的另一种变量声明方式
var foo = true; if (foo) { let bar = foo * 2; console.log(bar); } console.log(bar); // ReferenceError
在开发和修改代码的过程中,如果没有密切关注哪些块作用域中有绑定的变量,并且习惯性地移动这些块或者将其包含在其他的块中,就会导致代码变得混乱。为块作用域显式地创建块可以部分解决这个问题
var foo = true; if (foo) { { let bar = foo * 2; console.log(bar); } } console.log(bar); // ReferenceError
const
除了 let 以外,ES6 还引入了 const,与 let 不一样的是其值是固定的(常量)。
var foo = true; if (foo) { var a = 2; const b = 3; a = 3; // 正常 b = 4; // 错误 } console.log(a); // 3 console.log(b); // ReferenceError: b is not defined