块作用域

变量的声明应该距离使用的地方越近越好。

块作用域是用来对最小授权原则进行扩展的工具,将代码从函数中隐藏信息扩展为在块中隐藏信息。

块作用域指的是变量和函数不仅可以属于所处的作用域,也可以属于某个代码块(通常指 {} 内部)

with

用 with 从对象中创建出的作用域仅在 with 声明中而非外部作用域中有效。

try/catch

从ES3开始,try/catch结构在catch分句会创建一个块级作用域,其中声明的变量仅在 catch 内部有效。

1try {
2  throw new Error();
3} catch (err) {
4  console.log("catch", err);
5}
6console.log("global", err); // ReferenceError: err is not defined

let

在ES6中引入了 let 关键字,用来在任意代码块中声明变量。

let关键字可以将变量绑定到当前所有的任意作用域中(通常是 {} 的内部)

换句话说,let为其声明的变量隐式地劫持了所在的块作用域。

1{
2  let bar = 2;
3}
4console.log(bar); // ReferenceError: bar is not defined

垃圾收集

另一个块作用域非常有用的原因和闭包及回收垃圾的回收机制相关。

let循环

一个 let 可以发挥优势的典型例子就是 for 循环

1for (let i = 0; i < 10; i++) {
2  console.log("for", i);
3}
4console.log("global", i); // ReferenceError: i is not defined

for循环头部的let不仅将 i 绑定到了 for 循环的块中,事实上它将其重新绑定到了循环的每一个迭代中,确保使用上一个循环迭代结束时的值重新进行赋值。

1{
2  let j;
3  for (j = 0; j < 10; j++) {
4    let i = j; // 每个迭代重新绑定
5    console.log("for", i);
6  }
7}

const

除了 let 以外,ES6还引入了 const,同样可以用来创建块作用域变量,但其值是固定的(常量)。之后任何试图修改值的操作都会引起错误。