一、作用域的类型
1. 全局作用域(公司大门外)
- 范围:整个 JavaScript 文件
- 变量:像贴在公告栏上的信息,所有人可见
- 例子:
const companyName = "阿里"; // 全局变量,任何地方都能访问 function showCompany() {console.log(companyName); // 能访问 }
2. 函数作用域(独立办公室)
- 范围:函数内部
- 变量:像办公室抽屉里的文件,只有内部员工能访问
- 例子:
function departmentA() {const secret = "部门A的密码"; // 函数作用域变量console.log(secret); // 能访问 } departmentA(); console.log(secret); // 报错!外部无法访问
3. 块级作用域(会议室,ES6 新增)
- 范围:
{}
内部(如if
、for
、while
) - 变量:用
let
或const
声明,像会议纪要只能在会议室使用 - 例子:
if (true) {const meetingNote = "重要内容"; // 块级作用域console.log(meetingNote); // 能访问 } console.log(meetingNote); // 报错!外部无法访问
二、作用域链:权限的传递规则
1. 规则:像快递员送包裹
- 当前作用域找不到变量时,会一层层向上级作用域查找
- 直到全局作用域,找不到就报错
2. 代码示例:
const globalVar = "全局"; // 全局作用域function outer() {const outerVar = "外层"; // outer 函数作用域function inner() {const innerVar = "内层"; // inner 函数作用域console.log(innerVar); // 自己抽屉找到 → "内层"console.log(outerVar); // 上级办公室找到 → "外层"console.log(globalVar); // 公告栏找到 → "全局"}inner();
}outer();
三、关键细节:避免踩坑
1. var
的坑(没有块级作用域)
for (var i = 0; i < 3; i++) {setTimeout(() => console.log(i), 100); // 输出 3,3,3
}
// 原因:var 声明的 i 属于全局作用域// 正确写法(用 let 块级作用域):
for (let i = 0; i < 3; i++) {setTimeout(() => console.log(i), 100); // 输出 0,1,2
}
2. 变量提升(先上车后补票)
var
声明的变量会提升到作用域顶部,但值为undefined
let
和const
不会完全提升(存在暂时性死区)console.log(a); // undefined(var 变量提升) var a = 10;console.log(b); // 报错(let 不会提升) let b = 20;
四、作用域的重要性
- 避免命名冲突:不同作用域的同名变量互不影响
- 数据保护:函数内部的变量外部无法直接修改
- 管理内存:作用域结束后,内部变量可被垃圾回收
总结比喻
- 全局作用域:公司公告栏(随便看)
- 函数作用域:部门保险箱(需权限)
- 块级作用域:会议室白板(会后擦除)
- 作用域链:快递员送包裹(层层向上找地址)