块级作用域与函数作用域的区别
- 定义范围:
- 函数作用域:由函数声明界定,函数内部定义的变量在整个函数体内都可访问,函数外部不可访问。例如:
function outer() {
let a = 10;
console.log(a); // 10
}
console.log(a); // ReferenceError: a is not defined
- 块级作用域:由
{}
界定,在if
语句块、for
循环块、while
循环块等使用{}
的结构内,块级作用域内定义的变量在块外部不可访问。例如:
if (true) {
let b = 20;
console.log(b); // 20
}
console.log(b); // ReferenceError: b is not defined
- 声明提升:
- 函数作用域:函数作用域中,变量声明会提升到函数顶部,但赋值不会提升。例如:
function func() {
console.log(c); // undefined
var c = 30;
}
func();
- 块级作用域:在ES6之前,JavaScript没有块级作用域的概念,也就不存在块级作用域的声明提升。ES6引入
let
和const
后,块级作用域有了声明提升,但变量存在暂时性死区(TDZ)。例如:
{
console.log(d); // ReferenceError: Cannot access 'd' before initialization
let d = 40;
}
常见的块级作用域符号
{}
:在if
语句、for
循环、while
循环、switch
语句等结构中使用{}
来界定块级作用域。例如:
for (let i = 0; i < 5; i++) {
console.log(i);
}
console.log(i); // ReferenceError: i is not defined
try - catch
块:try
和catch
块也形成块级作用域。例如:
try {
let e = 50;
} catch (error) {
let f = 60;
}
console.log(e); // ReferenceError: e is not defined
console.log(f); // ReferenceError: f is not defined
对变量访问和声明提升的影响
- 变量访问:
- 在块级作用域中,使用
let
或const
声明的变量只能在块内访问,块外访问会报错。这有助于防止变量泄露到不必要的作用域中。
- 函数作用域中,使用
var
声明的变量在整个函数内可访问,若在函数内不同位置多次声明同一var
变量,实际上是同一个变量。
- 声明提升:
- 块级作用域中
let
和const
声明的变量存在暂时性死区,从块的开始到声明变量的位置,变量不可访问和使用,声明提升但不初始化。
- 函数作用域中
var
声明的变量提升到函数顶部,可在声明前使用,值为undefined
,但赋值操作不会提升。