ES6: let及const注意事项

282 阅读3分钟

小知识,大挑战!本文正在参与“程序员必备小知识”创作活动。

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'

相当于隐式的把变量提升到了顶部去声明,这样看似不太严谨的操作,容易让一些不太熟悉的人混乱,那么letconst声明变量,就不会出现变量提升,并且会报错

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常量

  1. 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
  1. 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.
  1. 示例出现过几次TypeErrorconstant,这种固定类型错误如果看到可以快速定位到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

因此,暂时性死区,就是不能在初始化之前使用变量

而暂时性死区的提出,也是为了防止声明之前就使用,避免一些运行上的错误