小知识,大挑战!本文正在参与“程序员必备小知识”创作活动。
let和const的提出是为了解决var声明变量的不足,我现在在项目中已经不会再出现var了,那么频繁的使用,就得深入的去理解
变量提升
用var声明变量会出现变量提升的问题,什么是变量提升呢
console.log(jojo) // error: jojo is not defined
会报错jojo is not defined
console.log(jojo)
var jojo = 'i am jojo' // undefined
会打印undefined
出现这样的原因是变量提升机制导致,具体运行时会解析成如下格式
var jojo
console.log(jojo)
jojo = 'i am jojo'
相当于隐式的把变量提升到了顶部去声明,这样看似不太严谨的操作,容易让一些不太熟悉的人混乱,那么let和const声明变量,就不会出现变量提升,并且会报错
console.log(jojo)
let jojo // error: Uncaught ReferenceError: jojo is not defined
禁止重复声明
var允许重复声明变量,因为编辑器会在判断有已经声明的同名变量时忽略var,然后直接赋值或覆盖
var jojo = 1
var jojo = 2
console.log(jojo) // 2
这样的问题在我看来也是不严谨的操作,于是let的出现也是为了解决这个问题
let jojo = 1
let jojo = 2
console.log(jojo) // error Uncaught SyntaxError: Identifier 'jojo' has already been declared
Uncaught SyntaxError: Identifier 'jojo' has already been declared, 出现重复声明的错误, 因此
用let需要避免重复声明
块级作用域
es5没有块级作用域的概念,在es6中提出了块级作用域的概念,块级作用域可以声明作用域外无法访问的变量,块级用 {} 表示
for(let i=1;i<5;i++){
console.log(i)
}
console.log(i)
// 1
// 2
// 3
// 4
// error: Uncaught ReferenceError: i is not defined
{} 内声明的i,在外部便访问不到,以后在for内使用let,可以避免一些麻烦,比如经典的循环与闭包问题
let arr = []
for(var i=0;i<5;i++){
arr.push(function(){
console.log(i)
})
}
arr.forEach(item=>{
console.log(item())
})
// 5
// 5
// 5
// 5
// 5
想要得到0-4,需要加入闭包来解决
let arr = []
for(var i=0;i<5;i++){
(function(i){
arr.push(function(){
console.log(i)
})
})(i)
}
arr.forEach(item=>{
console.log(item())
})
// 0
// 1
// 2
// 3
// 4
const常量
- const声明的是常量,不能通过赋值改变值或者重复声明也是不允许的,因此每次声明的时候都必须进行初始化,而let则不需要
// 必须初始化
const name
// error: Uncaught SyntaxError: Missing initializer in const declaration
// 不能通过赋值改变值
const name = "jojo"
name = "dio"
console.log(name)
// error: Uncaught TypeError: Assignment to constant variable.
// let不需要赋初始值
let name // undefined
let name = "jojo" // jojo
- const如果赋予的是对象,则可以修改对象属性,但不能直接修改已声明的对象
const obj = {
name: "jojo"
}
obj.name = "dio"
console.log(obj.name) // dio
const obj = {
name: "jojo"
}
obj = {}
console.log(obj)
// error: Uncaught TypeError: Assignment to constant variable.
- 示例出现过几次TypeError和constant,这种固定类型错误如果看到可以快速定位到const
暂时性死区
let和const都是块级作用域,在最开始解释了变量提升,具体点应该是指将创建和初始化都提升了
(function(){
console.log(name)
let name = "jojo"
}())
// error: Uncaught ReferenceError: Cannot access 'name' before initialization
之前说let和const没有变量提升,其实换一个说法具体一点应该是let和const有创建提升,但是没有提升初始化
这里报错相当于是创建了变量,但是没有提升变量,所以不是name is not defined
因此,暂时性死区,就是不能在初始化之前使用变量
而暂时性死区的提出,也是为了防止声明之前就使用,避免一些运行上的错误