ES5关键字var
再没有let及const之前,我们一直用var来进行类型声明,那么var有什么缺点呢?
var声明的变量具有全局作用域及局部作用域,这有时会是一个麻烦的问题
!(function(){
console.log(b);
var b = 10;
})() //输出的值是什么?
输出的值是undefined,因为变量的声明会被提升,上述的代码等价于
!(function(){
var b;
console.log(b);
b = 10;
})()
或是循环中的变量被外部访问
var b = 2;
for(b = 0;b < 10;b++){
}
console.log(b);
输出的结果为10,可以看到循环内部的作用域影响到了外部作用域,var是不存在块级作用域的,因此变量及其容易被修改,而es6则对此作出了修改,推出了let及const两种新的变量声明
ES6关键字let及const
与其说ES6推出了新的变量声明关键字不如说是引入了块级作用域,ES6的块级作用域有如下特点
- 块级作用域可以理解为被两个大括号括起来的语句块
- 在块级作用域内定义的变量,外部是无法访问的 如for循环括号中let的变量只能在循环中使用
let变量声明了块级作用域,函数内部的变量不会再被隐式的全局定义,同时也不会进行声明的提升
例一:
!(function(){
console.log(b);
let b = 123;
})()
会出现如下错误:
这也证明了let不再具有变量的提升了,这种情况又叫暂时性死区
例二:
let b = 2;
for(let b = 0;b < 10;b++){
}
console.log(b);
输出结果为2,let构建的块级作用域使循环内外的互不影响。
总的来说let及const有以下几个特点:
- 在块级作用域下生效
- 不可重复声明
- 存在暂时性死区
- 不存在变量提升(即预解析)
但相比let,const应注意:
- 变量声明时必须立即赋值
- 如果声明的是简单类型的数据,变量的值不可改变
一般情况下,let更多是用来声明变量,而const用来声明常量,为什么呢?
因为const声明的实质是保证变量指向的内存地址所保存的数据不被改动
- 一般来讲,简单数据类型如Number,String,Boolean,值就保存在变量所指向的内存地址中,而复杂的数据类型如对象,数组及函数,变量所指向的内存地址,实际上保存的是指向实际数据的指针。所以const只能保证指向内存的指针的固定的,而指针指向的数据结构是否变化就无法控制了,因此const更多定义常量而非复杂数据类型,因为指向复杂数据类型时的const是不可靠的。