JavaScript的作用域系统是其最核心也最容易令人困惑的特性之一。本文将深入探讨从词法环境(Lexical Environment)到闭包(Closure)的完整作用域链机制,通过详细的代码示例、对比分析、可视化图表和实际应用场景,帮助您彻底理解JavaScript的作用域工作原理。
1. JavaScript作用域基础
1.1 作用域类型对比
作用域类型 |
定义位置 |
变量访问规则 |
创建时机 |
示例 |
全局作用域 |
所有函数外部 |
任何地方可访问 |
脚本加载时 |
var global = 1; |
函数作用域 |
函数内部 |
仅函数内可访问 |
函数调用时 |
function f() { var local = 2; } |
块级作用域(ES6+) |
{} 块内部 |
仅块内可访问 |
块执行时 |
if(true) { let block = 3; } |
模块作用域(ES6+) |
模块文件内部 |
仅模块内可访问 |
模块加载时 |
export const mod = 4; |
1.2 变量声明方式对比
声明方式 |
作用域 |
提升(Hoisting) |
重复声明 |
暂存死区(TDZ) |
全局对象属性 |
var |
函数作用域 |
是 |
允许 |
无 |
是 |
let |
块级作用域 |
否(存在TDZ) |
不允许 |
有 |
否 |
const |
块级作用域 |
否(存在TDZ) |
不允许 |
有 |
否 |
function |
块级作用域 |
是 |
允许 |
无 |
是 |
var globalVar = 'global';
let blockScoped = 'outer';
function scopeExample() {
var functionScoped = 'function';
let innerBlock = 'inner';
if (true) {
var hoisted = 'hoisted';
let blockScoped = 'block';
const constant = 'constant';
console.log(blockScoped);
console.log(innerBlock);
}
console.log(hoisted);
console.log(blockScoped);
console.log(constant);
}
2. 词法环境(Lexical Environment)详解
2.1 词法环境组成结构
2.2 环境记录类型对比
环境记录类型 |
创建场景 |
存储内容 |
特殊行为 |
声明式环境记录 |
函数、catch块、块作用域 |
let/const/函数/参数 |
处理词法声明的绑定 |
对象环境记录 |
with语句、全局环境 |
对象属性 |
属性访问代理到对象 |
模块环境记录 |
ES6模块 |
模块导出 |
处理导入/导出绑定 |
全局环境记录 |
脚本全局环境 |
全局变量/函数 |
混合了声明式和对象记录 |
2.3 作用域链构建过程
const globalVar