在 JavaScript 中用 var, let, 以及 const 有什么差别?什么时候该用哪个?
2023年2月9日
「在 JavaScript 中用 var
, let
, 以及 const
有什么差别?」是在前端、JavaScript 面试中常见的考题。在面试时可以先大方向地列点说出异同之处,然后再针对每一个点进行深入说明。以下是以第一人称撰写的参考拟答。
var
, let
, 以及 const
都是在 JavaScript 用来做变数宣告的保留字,在 JavaScript 早期只有 var
,直到 ES2015 (ES6) 时才加入了 let
与 const
。
他们之间主要有 4 个不同
- 在作用域上,
var
可以是全域、也可以是以函式作为范围;let
与const
则是以区块作为范围。 - 在宣告上,
var
可以被重复宣告,但是let
与const
则不行。 - 在提升上,
var
宣告的变数会自动初始化值为undefined
,因此在宣告前就使用变数,不会出现错误,而会是undefined
;但是let
与const
宣告的变数则不会自动初始化,而是会进到暂时死区(TDZ),因此在let
与const
宣告变数前使用该变数,会出现错误。 let
与const
在绝多数面向都是一样,两者的一大区别在于,用let
宣告的变数可以重新赋值,但是用const
的不行。
作用域的差别
在作用域上,var
可以是全域、也可以是以函式作为范围,let
与 const
则是以区块作为范围。 ;当我们在一个文件的最外层使用 var
来宣告变数,这时它的范围会是全域,因此当我们在 console 当中输入
var greeting = "hello";
我们可以接着输入
window.greeting; // "hello"
其结果会是 hello
,但是用 let
与 const
宣告则不会有同样效果。而除了全域,var
在某个函式中范围则是该函式。
var
可以重复宣告
在宣告上,var
可以被重复宣告,但是 let
与 const
则不行。所以当使用 var
时,可以做到以下这样:
var greeting = "Hello! This ExplainThis :)";
var greeting = "ExplainThis is a website that helps you learn programming!";
let
可以重新赋值,但不能重复宣告,所以会如下面这样:
// 不行这样!不然会有 SyntaxError: Identifier 'greeting' has already been declared
let greeting = "Hello! This ExplainThis :)";
let greeting = "ExplainThis is a website that helps you learn programming!";
// 可以这样 :)
let greeting = "Hello! This ExplainThis :)";
greeting = "ExplainThis is a website that helps you learn programming!";
提升上的差别
在提升上,var
宣告的变数会自动初始化,因此在宣告前就使用变数,不会出现错误,而会是 undefined
,例如下面这样
console.log(greeting); // undefined
var greeting = "hi there";
但是 let
与 const
则不会,而是会进到暂时死区 (TDZ),因此在 let
与 const
宣告变数前使用该变数,会出现错误:
console.log(greeting); // Uncaught ReferenceError: greeting is not defined
let greeting = "hi there";
let
可以重新赋值 const
不行
let
与 const
在绝多数面向都是一样,两者的一大区别在于,用 let
宣告的变数可以重新赋值,但是用 const
的不行。
特别注意,这边指的差别是在于「赋值」,而不是改变某个变数。如果是改变某个变数,若该变数是原生值(primitive values),例如字串、数字,let
与const
都不能改变;但假如该变数是**物件(objects) **,则不论let
或const
在宣告后,都仍是可以改变该物件。
所以下面这个例子是可行的
const user = { name: "小明" };
user.name = "小王";
console.log(user); // {name: '小王'}
延伸问题:什么时候该用 let
? 什么时候用 const
?
关于这问题,没有一个标准答案。业界目前普遍的观点是多数时候都用const
,只有非得要重新赋值才用let
,甚至有一条 ESLint 的规则prefer-const 是在规范这个写法。
不过也有另一个观点,例如 React 核心团队的 Dan Abramov 就表示自己是看心情决定用哪一个,换句话说并没有一个固定规则。当然他也提到如果团队已经有某个使用的原则,那他会尊重团队订定出的使用原则,以代码的一致性为主。
这边附上 Dan Abramov 分享这题的片段