ES5 只有两种声明变量的方法:var命令和function命令。ES6 添加let、const、import和class命令。算起来,ES6 一共有 6 种声明变量的方法。
本文就主要来探讨let 和const这两种。
首先,我们回顾下作用域
作用域:负责收集并维护由所有声明的标识符(变量)组成的一系列查询,并实施一套非常严格的规则,确定当前执行的代码对这些标识符的访问权限。
下面我们来看看ES6的let有什么特别之处
只声明不赋值,初始值为undefined
var a;
a //undefined
let b;
b //undefined
var和let声明的变量,初始值是为undefined的,就算是在严格模式下也是一样
不存在变量提升
a; //undefined
var a;
b //ReferenceError: b is not defined
let b;
var声明的变量会发生”提升“现象,即变量可以在声明之前使用,值为undefined。
而ES6的let命令声明的变量一定要在声明收使用,否则报错。
不能重复声明
var a=1;
var a=2;
a //2
let b=1;
let b=2;
b //Identifier 'b' has already been declared
var c=1;
let c=2;
c //Identifier 'b' has already been declared
let不允许在相同作用域内,重复声明同一个变量。注意是相同作用域内不能。
块级作用域
ES6之前是没有块级作用域的(只是函数本身“封闭”的特性和闭包去模拟的块级作用域),严格的块级作用域比如
{
//我就是块级作用域,这花括号包围的区域是独立一个作用域的,在这里声明的标识符(变量)在外界是访问不到的
}
//典型的说明js没有块级作用域的例子
var a=1;
function foo(){
console.log(a);
if(false){
var a=2;
}
}
foo(); //undefined
for(var i=0;i<10;i++){
//dosomething
}
i //10
第一个例子,我们在执行foo()后,原意是想通过访问外部的a,但是在函数里面在变量a提升到函数顶部了,所以a就是undefined。
第二个例子是我们在for里面的定义的变量泄漏成为了全局变量了。
而es6的let就是实际上就是js新增的块级作用域
let a=1;
function foo(){
console.log(a);
if(false){
let a=2;
}
}
foo(); //1
for(let i=0;i<10;i++){
//dosomething
}
i //ReferenceError: i is not defined
我们只是把var换成let来声明变量,就达到了我们想要的结果了。并且只在let命令所在的代码块内有效。换句话说就是在let所处的位置上如果有{},那么这块区域就成立独立的作用域(块级作用域)
{
let a = 10;
var b = 1;
}
a // ReferenceError: a is not defined.
b // 1
分别用let和var声明了两个变量。然后在代码块之外调用这两个变量,结果let声明的变量报错,var声明的变量返回了正确的值。这表明,let声明的变量只在它所在的代码块有效。
以前我们用闭包解决的很多技巧现在用let就可以很方便的搞定了,
for(var i=0;i<10;i++){
setTimeout(function(){
console.log(i);
},i*1000);
}
我想每个一秒输出递增到10的数字,但是输出的都是10,这是因为i都是同处一个相同执行上下文,所以最终输出的都是10,es5的解决方式使用自执行函数。而由了let,只需要把var改为let就搞定了...
ES6可以让任意的作用域嵌套
比如
{
{let a=1;}
a //ReferenceError: a is not defined
}
{ let b=1;
{
console.log(b) //1
}
}
在块级作用域下,块级作用域可以任意嵌套。外层作用域无法读取内层作用域的变量。内层作用域可以定义外层作用域的同名变量(也是词法作用域,内部可以访问外作用域,外部不可以访问内部作用域)。
const
const和let的功能很类似。
const用来声明一个只读的常量。一旦声明,常量的值就不能改变。其他的基本一样。常量一般都用大写来区分。
在es6之前创建一个常量或者说常量属性(不可修改、重新定义或者删除)是结合属性的特性writable:false和configurable:false的,关于属性的特性有不动的读者可以先进行百度下哈,后面我专门整理文章再来详细探讨,现在我们只要知道属性的特性就是就是可以直接检测属性特性的方法。
value:属性的值
writable:决定是否可以修改属性的值
configurable:属性是否是可配置的,如果是,可以使用方法来修改其他属性描述性
enumerable:属性是否是可枚举的,简单说就是它能不能出现在for...in循环
//ES6之前实现常量属性
var obj={}
Object.defineProperty(obj,"CONSTANT ",{
value:10,
writable:false,
configuable:false
});
//ES6定义常量
let OTHERCONST=20;
对比可想而知...
const声明的变量不能改变值,这意味着,const一旦声明变量,就必须立即初始化,不能留到以后赋值。
const NUM = 1;
NUM // 1
NUM = 2; // TypeError: Assignment to constant variable.
这里要注意的是,const定义的如果是一个复合类型的值(对象),那const定义的常量存储的是这个对象的指针,他只是保证这个指针固定不变,并不是说我们不能对这个对象进行操作。
因此,将一个对象声明为常量必须非常小心。
const OBJ={};
OBJ.a=1;
OBJ.a //1
本文就到这里了,谢谢观看,如果错误,欢迎指正!
对本文有什么不理解的地方话也可以留言评论交流!!!
by zhengyepan
欢迎访问我的个人网站zhengyepan.com
欢迎讨论交流~