变量声明

Javascript中有三种声明变量的方式:var, let, const 虽然它们都能用来声明变量,但在作用域、变量提升、重复声明等方面有着重要区别

var name = "Kayn"; // 老式写法,有作用域问题
let age = 17; // 现代写法,块级作用域
const PI = 3.14159; // 常量,声明后不能修改

var 声明

var 是 JavaScript 最早的变量声明方式,但它有一些问题:

函数作用域

var 声明的变量只有函数作用域,没有块级作用域

function example() {
if (true) {
var x = 1;
}
console.log(x); // 输出 1,x 在整个函数内都可访问
}
// 对比块级作用域
for (var i = 0; i < 3; i++) {
// i 在这里声明
}
console.log(i); // 输出 3,i 泄漏到了全局作用域

变量提升

var 声明会被”提升”到函数或全局作用域的顶部

console.log(x); // undefined(而不是报错)
var x = 5;
// 实际上相当于:
var x; // 声明被提升到顶部
console.log(x); // undefined
x = 5; // 赋值仍在原位置

允许重复声明

var name = "Kayn";
var name = "Alice"; // 不会报错,但可能导致混淆
console.log(name); // "Alice"

let 声明

let 是 ES6 引入的现代变量声明方式,解决了 var 的问题:

块级作用域

function example() {
if (true) {
let x = 1;
}
console.log(x); // ReferenceError: x is not defined
}
// for 循环中的应用
for (let i = 0; i < 3; i++) {
// i 只在这个块内有效
}
console.log(i); // ReferenceError: i is not defined

暂时性死区

let 不会被提升到可用状态,在声明前访问会报错

console.log(x); // ReferenceError: Cannot access 'x' before initialization
let x = 5;

不允许重复声明

let name = "Kayn";
let name = "Alice"; // SyntaxError: Identifier 'name' has already been declared

const 声明

const 用于声明常量,具有 let 的所有特性,但有额外限制:

必须初始化

const PI = 3.14159; // 正确
const x; // SyntaxError: Missing initializer in const declaration

不能重新赋值

const name = "Kayn";
name = "Alice"; // TypeError: Assignment to constant variable

对象和数组的特殊情况

const 只是不允许重新赋值,但对象和数组的内容仍然可以修改

const person = { name: "Kayn" };
person.name = "Alice"; // 允许,修改对象属性
person.age = 17; // 允许,添加新属性
const numbers = [1, 2, 3];
numbers.push(4); // 允许,修改数组内容
// numbers = [5, 6, 7]; // 不允许,重新赋值会报错

选择建议

优先级顺序

  1. 优先使用 const:如果值不需要重新赋值
  2. 其次使用 let:如果值需要重新赋值
  3. 避免使用 var:除非在维护老代码

实际应用

// ✅ 推荐写法
const baseUrl = "https://api.example.com"; // 不会改变的值
let currentUser = null; // 可能会重新赋值
const users = []; // 数组本身不会重新赋值,但内容会变化
// ❌ 不推荐写法
var apiKey = "secret"; // 作用域问题
var counter = 0; // 可能导致意外的变量提升

作用域对比总结

声明方式作用域变量提升重复声明重新赋值
var函数作用域是允许允许
let块级作用域暂时性死区不允许允许
const块级作用域暂时性死区不允许不允许

常见陷阱

for 循环中的闭包问题

// 使用 var 的问题
for (var i = 0; i < 3; i++) {
setTimeout(() => {
console.log(i); // 输出三个 3
}, 100);
}
// 使用 let 的解决方案
for (let i = 0; i < 3; i++) {
setTimeout(() => {
console.log(i); // 输出 0, 1, 2
}, 100);
}

现代 JavaScript 开发中,正确使用 let 和 const 可以避免很多由作用域引起的 bug,让代码更加安全和可预测。