markdown
# JavaScript作用域详解
## 什么是作用域?
作用域就是变量和函数的"可见范围"。简单说,它决定了代码中哪些部分可以访问某个变量。
## 两种主要作用域类型
### 1. 全局作用域
在函数外部声明的变量,整个程序都可以访问
```javascript
let globalVar = "我是全局变量";
function showGlobal() {
console.log(globalVar); // 可以访问
}
showGlobal();
console.log(globalVar); // 也可以访问
2. 局部作用域(函数作用域)
在函数内部声明的变量,只有函数内部能访问
javascript
function localScope() {
let localVar = "我是局部变量";
console.log(localVar); // 可以访问
}
localScope();
console.log(localVar); // 报错!外部无法访问
块级作用域(ES6新增)
用 let
和 const
声明的变量具有块级作用域({}
就是一个块)
javascript
if (true) {
let blockVar = "块内变量";
console.log(blockVar); // 可以访问
}
console.log(blockVar); // 报错!超出作用域
作用域链(重要!)
JavaScript会从当前作用域开始,逐层向外查找变量
javascript
let outer = "外部变量";
function outerFunc() {
let middle = "中间变量";
function innerFunc() {
let inner = "内部变量";
console.log(inner); // 内部变量
console.log(middle); // 中间变量 ← 来自父作用域
console.log(outer); // 外部变量 ← 来自祖父作用域
}
innerFunc();
}
outerFunc();
常见误区案例
案例1:变量提升的坑
javascript
console.log(hoistedVar); // 输出undefined而不是报错
var hoistedVar = "我被提升了";
console.log(letVar); // 报错!
let letVar = "我不会被提升";
案例2:循环中的作用域
javascript
// 使用var(有问题)
for (var i = 0; i < 3; i++) {
setTimeout(() => {
console.log(i); // 全部输出3!
}, 100);
}
// 使用let(正确)
for (let j = 0; j < 3; j++) {
setTimeout(() => {
console.log(j); // 输出0,1,2
}, 100);
}
总结表格
关键字 | 作用域类型 | 是否提升 | 是否可重复声明 |
---|---|---|---|
var | 函数作用域 | 是 | 是 |
let | 块级作用域 | 否 | 否 |
const | 块级作用域 | 否 | 否 |
记住:良好的习惯是尽量使用 let
和 const
,避免使用 var
!