作用域与变量提升
作用域定义了变量的可访问范围,变量提升影响代码的执行顺序。
作用域类型
全局作用域
在代码任何地方都可访问:
JavaScript
var globalVar = 'global';
function test() {
console.log(globalVar); // global
}
函数作用域
只在函数内部可访问:
JavaScript
function test() {
var localVar = 'local';
console.log(localVar); // local
}
console.log(localVar); // ReferenceError
块级作用域
let 和 const 声明的变量具有块级作用域:
JavaScript
if (true) {
let blockVar = 'block';
const blockConst = 'block';
}
console.log(blockVar); // ReferenceError
console.log(blockConst); // ReferenceError
var、let、const对比
| 特性 | var | let | const |
|---|---|---|---|
| 作用域 | 函数作用域 | 块级作用域 | 块级作用域 |
| 变量提升 | 是(值为undefined) | 是(TDZ) | 是(TDZ) |
| 重复声明 | 允许 | 不允许 | 不允许 |
| 重新赋值 | 允许 | 允许 | 不允许 |
变量提升
var声明提升
声明提升到作用域顶部,值为 undefined:
JavaScript
console.log(a); // undefined
var a = 1;
console.log(a); // 1
// 等价于
var a;
console.log(a); // undefined
a = 1;
console.log(a); // 1
函数声明提升
整个函数定义提升:
JavaScript
sayHello(); // Hello
function sayHello() {
console.log('Hello');
}
函数表达式不提升
JavaScript
sayHi(); // TypeError: Cannot read property 'sayHi' of undefined
var sayHi = function() {
console.log('Hi');
};
暂时性死区(TDZ)
let 和 const 在声明前存在暂时性死区:
JavaScript
console.log(a); // ReferenceError: Cannot access 'a' before initialization
let a = 1;
TDZ从作用域开始到变量声明:
JavaScript
{
// TDZ开始
console.log(a); // ReferenceError
let a = 1; // TDZ结束
}
作用域链
内部作用域可访问外部作用域的变量:
JavaScript
let global = 'global';
function outer() {
let outer = 'outer';
function inner() {
let inner = 'inner';
console.log(inner); // inner
console.log(outer); // outer
console.log(global); // global
}
inner();
}
outer();
查找顺序:当前作用域 → 外层作用域 → ... → 全局作用域
常见问题
循环中的var
JavaScript
for (var i = 0; i < 3; i++) {
setTimeout(() => console.log(i), 100);
}
// 输出: 3, 3, 3
// 使用let解决
for (let i = 0; i < 3; i++) {
setTimeout(() => console.log(i), 100);
}
// 输出: 0, 1, 2
全局变量污染
JavaScript
// 避免使用var创建全局变量
var name = 'Tom'; // 成为window.name
// 使用let或const
const name = 'Tom'; // 不会污染全局
要点总结
var是函数作用域,let/const是块级作用域var声明提升值为undefined,函数声明整体提升let/const存在暂时性死区(TDZ),声明前不可访问- 作用域链由内向外查找变量
- 优先使用
const,其次let,避免var
📝 发现内容有误?点击此处直接编辑