es6 快速入门 系列 —— 变量声明:let和const

其余章节请看:javascript

es6 快速入门 系列html

变量声明:let和const

试图解决的问题

经典的 var 声明让人迷惑java

function demo1(v){
    if(v){
        var color='red'
    }
    console.log(color)
}
demo(1) // red

js引擎会将上面的 demo1 函数修改为下面的样子:es6

function demo2(v){
    var color;
    if(v){
        color='red'
    }
    ...
}

解决方法

var 声明改成 let 声明函数

function demo3(v){
    if(v){
        let color='red'
    }
    // 变量color在此处不存在
    console.log(color)
}

demo3(1) // 报错

let声明的用法与var相同。用 let 代替 var 来声明变量,就能够把当前做用域限制在当前代码块(指块级做用域)中。因为 let 声明不会被提高,所以开发者一般将 let 声明语句放在代码块顶部,以便整个代码块均可以访问code

最佳实践

起初,对不少js开发者来讲,let与他们实际想要的var同样,因此直接将var 替换成let。当更多的开发者迁移到es6后,另外一种作法日益普及:默认使用const,只有确实须要改变变量的值才使用let,可能大部分的值在初始化后不会再改变。htm

补充

块级做用域

之前只有函数做用域,es6新增了块级做用域(字符{和}之间的区域)blog

// 函数做用域:变量i在函数demo4中有效
function demo4(){
    if(true){
        var i = 1
    }
    console.log(i)
    
}
demo4() // 1
console.log(i) // 报错(i没有定义)
// 块级做用域:变量i只在if中的{和}之间有效
function demo5(){
    if(true){
        let i = 1
    }
    console.log(i)
    
}
demo5() // 报错(i没有定义)

禁止重复声明

假设做用域中存在某变量(i),此时再用 letconst 关键字声明变量(i),就会抛出错误ip

var a = 1;
// 重复声明,抛出语法错误
let a = 1;
var a = 1;
if(1){
    // 不会抛出错误(没有重复声明)
    let a = 1;
}

const声明

es6提供 const 关键字来声明常量作用域

常量必须一开始就初始化

// 正确
const i = 1
// 报错(常量未初始化)
const j;

不能够为 const 定义的常量再赋值(但容许修改值)

// 报错
const i = 1;
i = 2;
const obj = {}
// 正确(容许修改值)
obj.i = 1
// 错误(不容许修改绑定)
obj = {}

临时死区

用 let 或 const 声明的变量,会先存放在临时死区(TDZ)中,只有执行过变量声明语句后,变量才从TDZ中移除

if(true){
    // 报错(访问临时死区中的变量,会报错)
    console.log(typeof i)
    let i = 1
}

循环中的块做用域绑定

var 声明让开发者建立函数很是困难

var funArr = []

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

funArr[0]() // 5
funArr[1]() // 5

咱们的预期是输出0~4,这里却所有输出5

能够用当即调用函数表达式(IIFE)来达到目的,就像这样:

var funArr = []

for(var i = 0; i < 5; i++){ 
    funArr.push(function(i){
        return function(){
            console.log(i)
        }
    }(i))
}

funArr[0]() // 0
funArr[1]() // 1

但咱们能够用更简单的方式:循环中用 let 声明

var funArr = []
// 循环中用let声明:var 改用 let声明
for(let i = 0; i < 5; i++){
    // let声明模仿上述例子中 IIFE 所作的一切(每次循环都建立一个新变量i,给新变量i赋值),
    // 如今完全删除 IIFE 以后仍可获得预期的结果
    funArr.push(function(){
        console.log(i)
    })
}

funArr[0]() // 0
funArr[1]() // 1

注:let声明在循环内部的行为是标准中专门定义的,不必定与 let 的不提高特性相关

全局块做用域绑定

var 声明的变量,会覆盖已存在的全局属性;let 和 const 声明的变量不会覆盖全局属性

// 覆盖全局属性RegExp
var RegExp = 'hello'
console.log(window.RegExp) // hello
let RegExp = 'hello'
console.log(window.RegExp) // RegExp() { [native code] }
console.log(RegExp) // hello

其余章节请看:

es6 快速入门 系列

相关文章
相关标签/搜索