作用域 - [[scope]]
GO
- 全局执行上下文
AO
- 函数执行上下文
let/const - 块级作用域 { }
- 不能在同一作用域下重复声明 {let a = 1; let a = 2;}
- 不会跟 var 一样声明提升,会产生一个
TDZ (暂时性死区)
- TDZ - Temporal Dead Zone 暂时性死区
- 只能在当前的作用域下生效
- const 一旦定义必须赋值,并且值不能被更改
!!!特别注意
函数的参数区域()
内也会有自己的作用域
里面的参数声明也会有暂时性死区
TDZ 示例
// 报错 SyntaxError: Identifier 'a' has already been declaredfunction
test(a) {
let a = 1
}
test()
var a = a // 因为 var 声明会变量提升
console.log(a); // undefined
let b = b // 使用 let 声明则不会变量提升,如果在声明赋值前会产生一个 TDZ
console.log(b); // 报错
// 在函数的参数声明中也是如此,所以我们可以把函数的参数声明也看做成是一个独立的作用域
function test(x = y, y = 2) {
console.log(x, y);
}
借用块级作用域的特性,可以很好的解决 var
声明在函数作用域以及全局作用域的属性覆盖问题
for (var i = 0; i < 10; i++) {
setTimeout(
() => {
console.log(i) // 10 个 10
}, 0);
}
for (let i = 0; i < array.length; i++) {
setTimeout(
() => {
console.log(i) // 0, 1, 2, 3, 4, 5, 6, 7, 8, 9
}, 0);
}
因为 var
不受块级作用域的限制,所以他会逐级往外提升。
当 let
声明碰到已经声明过的变量名则会报错
// 报错 Identifier 'a' has already been declared
{
let a = 1
{
var a = 10
console.log(a);
}
}
var
声明会逐级往外提升,但他不会入侵到块级作用域内部
所以这里的报错原因是 x 的 let 声明 引用了自己的变量 x,而 x 这时还未被声明成功,所以导致报错
var x = 1
{
let x = x // 报错原因在这里
}
函数参数内部的作用域
let x = 1
function foo(x, y = function () { x = x },) {
y() // 此时函数中的 x 抓住的是参数中的 x 所以外部的 x 依然等于 1
// 如果将 参数 x 和 y 的位置的调换则会报错
console.log(x); // undefined
}
console.log(x); // 1
foo(2)