let/var/const和无关键字声明变量有有何不同?
没有关键字
在变量赋值之前没有关键字存在,要么赋值给一个不存在的全局变量,要么重新分配给已声明的变量.在非严格模式下,如果变量没有声明,它将赋值为全局对象(浏览器中的window
)的一个属性.在严格模式下,它将抛出一个错误阻止不需要的全局变量被创建.
var
直到ES2015var
仍是默认的声明语句.它创建了一个函数作用域,可以重新分配和重新声明.然而,由于缺少块作用域,如果变量在一个包含异步回调的循环中再次使用的话.他可能会造成问题,因为变量将继续存在于块作用域之外.
下面,等到setTimeout回调执行时,循环已经完成啦.而且变量i
的值是10
,因此,所有这10个回调在这个函数作用域下引用了同一个可用的变量
for (var i = 0; i < 10; i++) {
setTimeout(() => {
// 打印 `10` 10 次
console.log(i)
})
}
/* 使用 `var` 的解决方案 */
for (var i = 0; i < 10; i++) {
// 作为参数传递进去
setTimeout(console.log, 0, i)
}
for (var i = 0; i < 10; i++) {
// 创建一个函数作用域
;(i => {
setTimeout(() => {
console.log(i)
})
})(i)
}
let
let
在ES2015中引入,而且是新的变量声明推荐的方法,它之后将被重新分配.试图重新声明一个变量将会抛出错误.它是块级作用域,因此在循环中可以在迭代中保持它的作用域.
for (let i = 0; i < 10; i++) {
setTimeout(() => {
// 打印 0, 1, 2, 3, ...
console.log(i)
})
}
const
const
在ES2015中引入,而且是新的变量声明推荐的方法,它之后不能被重新分配,即使对象是可变的(只要对象的引用不变就行).它是块级作用域而且不能被重新分配
const myObject = {}
myObject.prop = "hello!" // 没有错误
myObject = "hello" // 抛出错误
小贴士
- 所有的声明都会被提升到它们的作用域顶部.
- 然而,
let
和const
有一个叫暂时性死区的概念. 虽然声明被提升啦,但有一段时间在进入作用域和被声明之间它们是不能访问的. - 给你一个使用
var
的常见问题,和let
如何解决它,以及保留var
的解决方案 var
应该尽可能的避免使用,推荐const
作为所有变量的默认声明,除非它们之后会被重新分配,则使用let