主题
变量与声明
变量用于给数据取名,并在后续代码里反复引用。JavaScript 目前最常见的声明方式有三种:let、const 和 var。
为什么需要变量
变量的作用不是“把值存起来”这么简单,它更重要的价值是:
- 给数据一个稳定名字
- 在不同语句之间共享结果
- 让表达式更易读、可复用
js
const price = 100
const count = 2
const total = price * count三种声明方式
let
let 用于声明一个可以重新赋值的变量。
js
let message = 'hello'
message = 'world'适合:
- 后续会发生变化的状态
- 循环计数器
- 条件分支里需要重新赋值的变量
const
const 用于声明一个不能被重新赋值的绑定。
js
const siteName = 'vfan docs'
// siteName = 'other' // TypeError需要注意,const 约束的是“变量绑定不能改”,不等于“值一定完全不可变”。
js
const user = {
name: 'Lee',
}
user.name = 'Vfan'这里修改的是对象内部属性,不是重新给 user 赋新值,所以是允许的。
var
var 是早期 JavaScript 的变量声明方式,现在只在兼容旧代码或理解历史代码时需要重点掌握。
js
var count = 1现代开发里通常不再主动使用 var,主要原因是它的作用域和提升规则更容易引发误解。
let、const、var 的主要区别
是否允许重新赋值
let:允许const:不允许var:允许
作用域
let:块级作用域const:块级作用域var:函数作用域,不具备真正的块级作用域
js
if (true) {
let a = 1
const b = 2
var c = 3
}
// console.log(a) // a is not defined
// console.log(b) // b is not defined
console.log(c) // 3重复声明
js
let value = 1
// let value = 2 // SyntaxErrorjs
var count = 1
var count = 2var 允许同一作用域内重复声明,这也是它更容易制造隐藏问题的原因之一。
提升与暂时性死区
var 的提升
var 声明会在进入作用域时先被创建,因此声明前访问它不会报“未定义变量”,而是得到 undefined。
js
console.log(a) // undefined
var a = 1这等价于概念上的:
js
var a
console.log(a)
a = 1let 和 const 的暂时性死区
let 和 const 也会进入作用域,但在真正执行到声明语句之前,不能被访问。
js
{
// console.log(count) // Cannot access 'count' before initialization
const count = 1
}这段声明前不可访问的区域,通常称为暂时性死区。
const 一定要初始化
const 声明时必须同时赋值:
js
const id = 1下面这种写法会报错:
js
// const id因为 const 不允许先声明、后赋值。
命名约定
变量名通常需要满足以下规则:
- 可以包含字母、数字、
$、_ - 不能以数字开头
- 不能使用保留字
常见约定:
- 普通变量使用小驼峰,例如
userName - 构造函数或类使用大驼峰,例如
UserProfile - 真正意义上的常量通常用全大写加下划线,例如
MAX_RETRY_COUNT
常见误区
const 不是“深度不可变”
js
const config = {
retry: 3,
}
config.retry = 5如果需要真正冻结对象,还要结合 Object.freeze() 等手段,但它也只是一层冻结。
不要为了“以后可能改”就默认全用 let
如果一个绑定本来就不需要重新赋值,优先用 const。这样可以更清楚地表达意图,也能减少无意修改。
var 在循环里容易出问题
js
for (var i = 0; i < 3; i++) {
setTimeout(() => {
console.log(i)
}, 0)
}结果通常是:
js
3
3
3因为所有回调共享同一个 i 绑定。改成 let 后,每次迭代都会生成新的绑定:
js
for (let i = 0; i < 3; i++) {
setTimeout(() => {
console.log(i)
}, 0)
}使用建议
- 默认优先使用
const。 - 只有在明确需要重新赋值时,才使用
let。 - 现代代码中尽量避免新增
var。 - 当看到声明前访问、循环闭包、重复声明这类问题时,优先排查是不是
var导致的。
