JavaScript 中的块级作用域,除 with 语句和 for 语句外,基本可以通过大括号 {} 分辨。而 if / else 语句、while 语句和 do / while 语句在不使用大括号时并不会生成块级作用域。若在循环语句(包括while 语句、 do / while 语句和 for 语句)中使用大括号,则会生成对应循环次数的块级作用域。具体代码如下:
// 直接由大括号组成的块级作用域
{ /* 作用域1 */ }
// try / catch / finally 语句
try{ /* 作用域1 */ }
catch(err){ /* 作用域2 */ }
finally{ /* 作用域3 */ }
// with 语句,没有大括号也存在块级作用域
with(x) /* 作用域1 */ ;
// 或 with(x){ /* 作用域1 */ }
// with 语句中通过 a 取到的是 obj 的属性 a 的值,而非全局变量 a 的值
var obj={ a: 100 }
var a=200
with (obj) console.log(a) // 100
但 for 循环语句中不使用大括号也可能(不是一定)会生成一定数量的块级作用域。在 for 循环的条件中无变量声明或使用 var 声明变量,不会生成块级作用域;使用 let / const 声明变量 / 常量时,则会生成与循环次数相对应的块级作用域。具体见如下代码:
// 以下 for 循环使用 var 声明全局变量,不需要生成块级作用域
// 打印的 i 是递增的
for(var i=0; i<10; i++) console.log(i)
// 打印的 j 全为 10
for(var j=0; j<10; j++) setTimeout(()=>console.log(j),100)
// 变量 i 和 j 均可在全局中访问
i // 10
j // 10
// 以下 for 循环使用 let 声明循环变量,即会生成与循环次数相对应的块级作用域
// 打印的 i 是递增的
for(let i=0; i<10; i++) console.log(i)
// 打印的 i 是递增的
for(let i=0; i<10; i++) setTimeout(()=>console.log(i),100)
// 变量 i 无法在 for 语句外访问
i // i is not defined
----- 极客时间《JavaScript 核心原理解析》学习笔记 Day 5 -----