JavaScript 中 var 与 let 区别详解
·
JavaScript 中 var 与 let 区别详解(通俗版)
1. 文档前言
本文档旨在用通俗语言+代码示例+生活类比的方式,帮助 JavaScript 初学者清晰理解 var 和 let 两种变量声明方式的核心区别,避免实际编码中因变量作用域问题导致的 bug。
2. 核心区别解析
2.1 区别1:作用域范围(变量能被“看到”的区域)
2.1.1 var:函数作用域(“大大咧咧”,范围广)
- 通俗解释:用
var声明的变量,只要在同一个函数里,不管藏在多少层{}(如 if、for 块)里,整个函数内的代码都能“看到”它。 - 代码示例:
function 家里() { // if 块相当于“卧室” if (天气好) { var 玩具 = "积木"; // 用 var 声明玩具 } // 出了卧室(if块),还能访问到玩具 console.log(玩具); // 输出:积木(不报错) } 家里(); - 生活类比:你在卧室藏了个玩具,家里所有人(整个函数)都能找到它,不会因为玩具在卧室就找不到。
2.1.2 let:块级作用域(“有规矩”,范围小)
- 通俗解释:用
let声明的变量,只在它所在的那对{}里有效,出了这对{},代码就“看不到”它了。 - 代码示例:
function 家里() { // if 块相当于“卧室” if (天气好) { let 零食 = "薯片"; // 用 let 声明零食 } // 出了卧室(if块),找不到零食 console.log(零食); // 报错:Uncaught ReferenceError: 零食 is not defined } 家里(); - 生活类比:你在卧室藏了包薯片,只有在卧室里(当前
{}内)能找到,出了卧室就没人知道薯片在哪了。
2.2 区别2:提前使用(变量声明前能否访问)
2.2.1 var:可以提前用,但值是 undefined
- 通俗解释:
var声明的变量会被“偷偷提到”当前作用域的最前面(专业叫“变量提升”),所以能在声明代码之前用它,但此时变量还没赋值,值是undefined。 - 代码示例:
// 声明前访问变量 console.log(苹果); // 输出:undefined(能访问,但没值) // 正式声明变量 var 苹果 = "红富士"; - 生活类比:妈妈早上说“下午买苹果”,你早上就能跟别人提“家里要吃苹果”,但此时苹果还没买回来(值为
undefined)。
2.2.2 let:提前用会直接报错(“暂时性死区”)
- 通俗解释:
let声明的变量也会“提升”,但在正式声明代码执行前,变量处于“禁区”(专业叫“暂时性死区”),谁都不能碰,一碰就报错。 - 代码示例:
// 声明前访问变量 console.log(香蕉); // 报错:Uncaught ReferenceError: Cannot access '香蕉' before initialization // 正式声明变量 let 香蕉 = "黄香蕉"; - 生活类比:妈妈还没说要给你买香蕉,你就跟别人说“家里有香蕉”,妈妈会直接纠正你:“哪来的香蕉?还没买呢!”(报错)。
2.3 区别3:重复声明规则(同一范围能否重名)
2.3.1 var:允许重复声明,后面的覆盖前面的
- 通俗解释:在同一个作用域里,
var可以给同一个变量名重复赋值,后面的赋值会把前面的“覆盖”掉,不会报错。 - 代码示例:
var 宠物 = "猫"; // 第一次声明:宠物是猫 var 宠物 = "狗"; // 第二次声明:宠物改成狗(不报错) console.log(宠物); // 输出:狗(后面的覆盖了前面的) - 生活类比:你先给宠物起名“咪咪”(猫),后来觉得不好听,改成“旺财”(狗),家里人都会认“旺财”这个新名字。
2.3.2 let:禁止重复声明,重名直接报错
- 通俗解释:在同一个作用域里,
let不允许给同一个变量名重复声明,哪怕想改值也不能用let重写,否则直接报错。 - 代码示例:
let 宠物 = "猫"; // 第一次声明:宠物是猫 let 宠物 = "狗"; // 第二次声明:直接报错 // 报错:Uncaught SyntaxError: Identifier '宠物' has already been declared - 生活类比:你已经给宠物起名“咪咪”了,再想让它叫“旺财”,家里人会说:“不行!名字不能随便重起,只能叫咪咪!”(报错)。
2.4 区别4:全局作用域中的特殊表现(与 window 对象的关系)
在浏览器的全局环境(不在任何函数里)中,var 和 let 还有个关键区别:
2.4.1 var:全局变量会变成 window 的属性
- 通俗解释:用
var声明的全局变量,会自动“绑定”到浏览器的window对象上,成为window的一个属性。 - 代码示例:
var 全局变量_var = 100; // 全局声明 var 变量 console.log(window.全局变量_var); // 输出:100(变量成了 window 的属性)
2.4.2 let:全局变量不会绑定到 window
- 通俗解释:用
let声明的全局变量,只是单纯的“全局变量”,不会和window产生关联,window上找不到它。 - 代码示例:
let 全局变量_let = 200; // 全局声明 let 变量 console.log(window.全局变量_let); // 输出:undefined(和 window 没关系)
3. 核心区别总结表
| 对比维度 | var 特性 | let 特性 |
|---|---|---|
| 作用域范围 | 函数作用域(函数内都可见) | 块级作用域(仅所在 {} 内可见) |
| 提前使用(声明前访问) | 允许,值为 undefined |
禁止,报错(暂时性死区) |
| 同一作用域重复声明 | 允许,后面覆盖前面 | 禁止,直接报错 |
| 全局环境与 window 关系 | 会成为 window 的属性 | 不会绑定到 window |
4. 推荐实践
在 ES6(2015年)之后,let 解决了 var 导致的很多问题(如变量泄漏、重复声明覆盖等),因此:
- 优先使用
let声明“会变的值”(如循环变量、需要修改的状态); - 若变量值不会变(如常量),用
const(和let作用域规则一致,只是不能改值); - 尽量避免使用
var,减少代码出错概率。
更多推荐


所有评论(0)