📚 学习笔记:ES6 块级作用域与函数声明

100 阅读3分钟

一、块级作用域与 let / const

✅ ES6 引入了块级作用域

  • 使用 {} 创建一个独立的作用域。
  • 在这个作用域中使用 letconst 声明的变量只在该作用域内有效。

✅ 暂时性死区(Temporal Dead Zone, TDZ)

  • 定义:在代码块内,使用 letconst 声明变量之前,该变量处于“暂时性死区”,不可访问。
  • 本质:变量已经在作用域中存在,但尚未初始化,因此不能访问。
  • 示例
    typeof x; // ReferenceError: Cannot access 'x' before initialization
    let x;
    

⚠️ typeof 不再是安全操作

  • 对未声明的变量使用 typeof 返回 "undefined"
  • 对处于 TDZ 中的变量使用 typeof 会抛出错误。
    typeof undeclaredVar; // "undefined"(未声明)
    typeof x; // ReferenceError(x 已声明,但未初始化)
    let x;
    

二、块级作用域中的函数声明

✅ ES6 允许在块级作用域中声明函数

{
    function foo() {
        return 1;
    }
    console.log(foo()); // 正常运行
}
console.log(foo()); // ReferenceError: foo is not defined
  • 函数只在当前块级作用域中有效。
  • 行为类似于 let,不会泄漏到外部。

⚠️ 浏览器环境 vs 非浏览器环境(如 Node.js)

环境行为说明
浏览器函数声明会被提升到全局或函数作用域顶部,类似 var
Node.js 等非浏览器环境函数声明行为更像 let,存在 TDZ,不能在声明前访问

示例对比

if (true) {
    foo(); // 浏览器中正常,Node.js 中报错
    function foo() { return 'A'; }
}

💡 实际开发建议

  • 避免在块级作用域中声明函数,尤其是需要跨块使用的情况。
  • 如果必须使用,推荐使用函数表达式:
{
    const bar = function () {
        console.log("safe");
    };
}

三、严格模式下的函数声明限制

✅ 允许在块级作用域中声明函数的前提是:必须有大括号 {} 包裹

// 合法写法
'use strict';
if (true) {
    function foo() {}
}

❌ 非法写法:没有 {},语法错误

// 报错
'use strict';
if (true)
    function foo() {} // SyntaxError

📌 原因

  • 在严格模式下,函数声明只能出现在当前作用域的顶层或由 {} 构成的块级作用域内部。
  • 控制流语句(如 if, while)后直接跟函数声明是不被允许的。

四、总结 & 小贴士

项目内容
✅ 块级作用域通过 {} 创建,用 let/const 声明的变量只在该作用域中有效
⚠️ 暂时性死区变量已存在但未初始化,不能访问,否则报错
⚠️ typeof 安全性下降对于 TDZ 中的变量,也会报错
⚠️ 函数声明行为不一致浏览器中类似 var,其他环境类似 let
✅ 推荐写法使用函数表达式代替函数声明
🔒 严格模式限制控制流语句后不能直接写函数声明,必须用 {} 包裹

🧠 总结一句话

ES6 引入了块级作用域和暂时性死区,提升了变量控制的安全性和灵活性,但也带来了函数声明行为的复杂性和环境差异。为了代码的可读性和一致性,应优先使用函数表达式,并注意严格模式下的语法限制。