ES6+新特性,var、let 和 const 的区别
在 JavaScript 中,var
、let
和 const
都用于声明变量,但它们有一些重要的区别,主要体现在 作用域、可变性和提升机制 等方面。
1. 作用域(Scope)
-
var
:var
声明的变量是 函数作用域,也就是说,它只在函数内部有效。如果var
声明在函数外面,它的作用域就是全局的。如果var
在一个代码块内(如if
语句中)声明,它的作用域并不限于该代码块,而是整个函数或全局作用域。
if (true) { var a = 10; }
console.log(a);// 10,因为a是函数作用域或者全局作用域
-
let
和const
:let
和const
都是 块级作用域,这意味着它们的作用域限制在所在的代码块(如{}
包裹的部分)内。if (true) { let b = 20; const c = 30; } console.log(b); // ReferenceError: b is not defined console.log(c); // ReferenceError: c is not defined
这里,
let
和const
声明的变量只在if
语句的代码块内部有效。
2. 变量提升(Hoisting)
-
var
:var
声明的变量会 被提升到函数或全局作用域的顶部,但初始化不会被提升。所以,变量在声明之前仍然能访问到,但值为undefined
。console.log(a); // undefined,因为声明被提升,但赋值没有 var a = 5;
-
let
和const
:let
和const
声明的变量也会被提升,但 在初始化之前不能访问,如果访问它们会导致ReferenceError
。这就是所谓的 "暂时性死区"(Temporal Dead Zone, TDZ)。console.log(b); // ReferenceError: Cannot access 'b' before initialization let b = 10;
这样,
let
和const
声明的变量不能在声明之前访问。
3. 可变性(Mutability)
-
var
和let
: 都声明的是 可变变量,即你可以在后续重新赋值。示例:
var x = 10; x = 20; // 允许重新赋值 let y = 30; y = 40; // 也允许重新赋值
-
const
:const
声明的是 常量,意味着你声明时必须给它赋值,并且之后不能再修改它的绑定(不能重新赋值)。但是,如果const
绑定的是一个对象或数组,那么对象的内容是可以修改的(例如添加、删除属性或元素)。const z = 50; z = 60; // TypeError: Assignment to constant variable. const obj = { a: 1 }; obj.a = 2; // 这是合法的,修改对象的内容 console.log(obj.a); // 2
这里,
const
防止了对变量的重新赋值,但并不阻止修改对象的内容。
4. 全局作用域中的 var
与 let
/const
-
var
: 如果你在全局作用域中使用var
声明一个变量,它会成为全局对象(浏览器中的window
或 Node.js 中的global
)的属性。示例:
var globalVar = 'I am global'; console.log(window.globalVar); // 'I am global' 在浏览器中
-
let
和const
: 如果你在全局作用域中使用let
或const
,它们不会成为全局对象的属性。示例:
let globalLet = 'I am block-scoped'; console.log(window.globalLet); // undefined
总结对比
特性 | var | let | const |
---|---|---|---|
作用域 | 函数作用域 | 块级作用域 | 块级作用域 |
提升 | 变量提升,但值为 undefined | 变量提升,但不能在初始化前使用 | 变量提升,但不能在初始化前使用 |
可变性 | 可重新赋值 | 可重新赋值 | 不能重新赋值(但对象内容可修改) |
全局作用域行为 | 成为全局对象的属性 | 不会成为全局对象的属性 | 不会成为全局对象的属性 |
选择使用
- 如果你需要声明一个变量,并且后续可能会重新赋值,使用
let
。 - 如果你需要一个常量(值不变),使用
const
。 - 避免使用
var
,因为它的作用域是函数级别的,容易导致意外的错误,尤其是在复杂的代码中。