es6 let 和 const 命令
一.let
1.作用域
在javascript中只有全局作用域和函数作用域,并不存在块级作用域。这样,在使用时就会出现一些问题。 下面我们先来举例说明let块级作用域的使用。
也就是说,var声明的变量由于不存在块级作用域所以可以在全局环境中调用,而let声明的变量由于存在块级作用域所以不能在全局环境中调用。
非常经典的例子:
//var
var a=[];
for(var i=0;i<10;i++){
a[i]=function(){
console.log(i);
};
}
a[6](); //10
//let
var b=[];
for(let j=0;j<10;j++){
b[j]=function(){
console.log(j);
};
}
b[6](); //6
let定义的变量j具有块级作用域,作用域是for循环所包含的语句块。
这个for循环最终执行了10次,实际上会产生10个互相平行的块级作用域。在每个作用域里面,i的值分别是0,1,2,..,8,9。
当调用b[6]时,执行到console.log(j)这行语句时,解释器会沿着作用域链寻找j的值,结果向上一层就是这10个平行作用域中的第7个,其中j的值为6,于是就打印出了6。
还可以简单的理解成代码块:
代码块就是 { }包起来的代码 ,形成了一个作用域,简称块级作用域
比如:if for while
特点:只能在代码块里面使用
{
let a=12;
console.log(a);//打印出 12
}
console.log(a);//undefined
2.不存在变量提升
这里是说使用let不会像使用var一样存在一个变量提升的现象。
变量提升是什么呢?
变量提升就是,是把下面的东西提到上面。先使用后声明
//var 情况
var a=1;
console.log(a);
console.log(i);
var i=10;
//let 情况
let b=2;
console.log(b);
console.log(j);
let j=5;
那么可以以此类推,var定义变量:可以先使用,后声明;而let定义变量:只可先声明,后使用。
注意:这个如果转成es5,就不行。
3.暂时性死区
只要一进入当前作用域,所要使用的变量就已经存在,但是不可获取,只有等到声明变量的那一行代码出现,才可以获取和使用该变量。
var tmp = 123;
if (true) {
tmp = 'abc'; // ReferenceError
let tmp;
}
也就是说:虽然上面的代码中存在全局变量tmp,但是块级作用域内let又声明了一个局部变量tmp,导致后者绑定了块级作用域,所以在let声明变量前,对tmp赋值会报错。此即暂时性死区。
注意:ES6规定暂时性死区和不存在变量提升就是为了减少运行时的错误,防止在变量声明前就使用这个变量,从而导致意料之外的行为。
暂时性死区就是: 只要块级作用域内存在let,那么他所声明的变量就绑定了这个区域,不再受外部的影响。
暂时性死区即 Temperary Dead Zone,即TDZ。
注意:暂时性死区也意味着 typeof 不再是一个百分之百安全的操作。 如下:
if (true) {
console.log(typeof x);
let x;
}
这里如果没有let x,那么typeof x的结果是 undefined,但是如果使用了let x,因为let不存在变量提升,所以这里形成了暂时性死区,即typeof x也是会报错的。。。 从这里可以理解暂时性死区实际上就是这一部分是有问题的 。
4.不允许重复声明
function func (){
let b=100;
var b=10;
}
会报错。总结:
var与let的区别
①let具备块级作用域,var只有函数作用域
②let不允许重复声明
二.let用处
1.i的问题
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title></title>
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=0">
<meta name="apple-mobile-web-app-capable" content="yes">
<meta name="apple-mobile-web-app-status-bar-style" content="black">
<script>
window.onload=function(){
var aBtn=document.getElementsByTagName('input');
for(let i=0; i<aBtn.length; i++){
aBtn[i].onclick=function(){
console.log(i);//点击那个按钮就打印出它对应的索引
}
}
};
</script>
</head>
<body>
<input type="button" value="aaa">
<input type="button" value="bbb">
<input type="button" value="ccc">
</body>
</html>
总结:块级作用域其实就是匿名函数立即调用
匿名函数:(function(){
...
})();
三.const 命令
const声明一个只读的常量。一旦声明,常量的值就不能改变;声明后 const必须有值。
const a=12;
a=15;
console.log(a)//报错 ,定义了不能修改
const a;
a=15;
console.log(a)//报错 声明后const a必须有值
注意:
1.const的作用域与let命令相同:只在声明所在的块级作用域内有效。
2.const命令声明的常量也是不提升,同样存在暂时性死区,只能在声明的位置后面使用。
3.const不可重复声明常量。