Skip to content

JavaScript 中 varlet 的区别

一直不太清楚 JavaScript 中 var 与 let 的区别,于是今天好好了解了一下,主要有以下三大区别。

作用域

首先是作用域上的区别,var 的作用域是函数级别(function level)的,而 let 的作用域是块级别(block level)的。

如下面的例子:

javascript
function foo() { // function level start
	if (true) { // block level start
		var c = 1
		let d = 1
	} // block level end
	// this works well
	console.log(c)
	// ReferenceError: d is not defined
	console.log(d)
} // function level end

可以看到,由 let 定义的变量只有在同一块级作用域内才能访问到,而由 var 定义的变量则在同一函数级作用域中可以访问到。

重声明

var 声明的变量是可以被重新声明的,而且作用域与被重声明前相同。需要注意的是,在开发过程中要谨慎使用这一特性,它可能导致一些无法预测的错误。而 let 声明的变量是不允许重声明的,尝试重声明一个 let 变量会引发语法错误,提示你不应该重声明一个 let 变量。

javascript
// declaration
var a = 1
let b = 1

// redeclaration
var a = 2 // acceptable
let b = 2 // error

变量提升

使用 var 声明的变量会被提升到其直属函数级作用域中,这意味着你可以在声明并初始化一个变量前引用它,但其值为 undefined。而 let 变量则不会被提升到函数级作用域中,你只能在声明它以后进行引用。

javascript
// Using var
console.log(a)
// Output: undefined (due to hoisting)
var a = 5; console.log(a)
// Output: 5

// Using let
console.log(b)
// Output: ReferenceError: Cannot access 'b' before initialization
let b = 10
console.log(b)
// Output: 10

这里顺便引入 Temporal Dead Zone 的概念。TDZ 指的是一个从块级作用域的头端开始,到一个变量被初始化结束的区域。在 JavaScript 中,由 letconst 声明的变量是有 TDZ 的,而由 var 声明的变量由于经过了提升,则不具有 TDZ。

javascript
function foo() {
	console.log(myVar)
	// ReferenceError: Cannot access 'myVar' before initialization
	let myVar = "Hello, World!" // same as const
	console.log(myVar) // Outputs: Hello, World!
}

function bar() {
	console.log(myVar) // Outputs: undefined
	var myVar = "Hello, World!"
	console.log(myVar) // Outputs: Hello, World! 
}

Last updated: