Skip to main content

var vs let vs const

var 声明及变量提升机制

var 声明的变量,会被提升到当前作用域的顶部,但是赋值操作并不会提升。

function getValue(condition) {
if (condition) {
var value = 'blue'
return value
} else {
// value 变量在这里存在,值为 undefined
return null
}
// value 变量在这里存在,值为 undefined
}

块级声明

块级声明用于声明在指定块的作用域之外无法访问的变量。块级作用域存在于:

  • 函数内部
  • 块中(使用 包裹的代码)

let 声明

let 声明的变量只在块级作用域内有效,不存在变量提升。

禁止重复声明

let 不允许在相同作用域内,重复声明同一个变量。

var count = 30

let count = 40 // 会报错
var count = 30

if (condition) {
let count = 40 // 不会报错
}

const 声明

const 声明的变量只在块级作用域内有效,不存在变量提升。任何情况下,都不能修改 const 声明的变量。用 const 声明对象时,对象的引用不可修改,但是对象的属性可以修改。

临时死区

Javascript 引擎在扫描代码发现变量声明时,要么将它们提升到作用域顶部(遇到 var 声明),要么将声明放到 TDZ 中(遇到 let 和 const 声明)。访问 TDZ 中的变量会触发运行时错误。只有执行过变量声明语句后,变量才会从 TDZ 中移出,然后方可访问。

循环中的块级作用域绑定

循环中的函数

var funcs = []

for (var i = 0; i < 10; i++) {
funcs.push(function () {
console.log(i)
})
}

funcs.forEach(function (func) {
func() // 输出 10 次数字 10
})

可以通过 IIFE 来解决这个问题。

var funcs = []

for (var i = 0; i < 10; i++) {
funcs.push(
(function (value) {
return function () {
console.log(value)
}
})(i)
)
}

funcs.forEach(function (func) {
func() // 输出 0 到 9
})

循环中的 let 声明

var funcs = []

for (let i = 0; i < 10; i++) {
funcs.push(function () {
console.log(i)
})
}

funcs.forEach(function (func) {
func() // 输出 0 到 9
})

循环中的 const 声明

var funcs = []

for (const i = 0; i < 10; i++) {
funcs.push(function () {
console.log(i)
})
}

在执行到第二次循环时,会报错,因为 i 的值不能修改。

在 for-in 或 for-of 循环中,也可以使用 let 和 const 声明。下面这段代码应该不会报错:

var funcs = [],
object = {
a: true,
b: true,
c: true,
}

for (const key in object) {
funcs.push(function () {
console.log(key)
})
}

funcs.forEach(function (func) {
func() // 输出 a、b、c
})

全局块作用域绑定

当 var 声明的变量在全局作用域中时,会成为 window 对象的属性。在全局作用域中使用 let 和 const 声明的变量,不会成为 window 对象的属性。

Differences

  • var declarations are globally scoped or function scoped while let and const are block scoped.
  • var variables can be updated and re-declared within its scope; let variables can be updated but not re-declared; const variables can neither be updated nor re-declared.
  • They are all hoisted to the top of their scope. But while var variables are initialized with undefined, let and const variables are not initialized.
  • While var and let can be declared without being initialized, const must be initialized during declaration.