ES6 新增了let
来声明局部变量。它的用法类似于var
,其声明的变量只在let
命令所在的代码块内有效({}),而且有暂时性死区的约束 ====>引出let 到底会不会有变量提升
写一个常见的变量提升的例子
var a = 100;
fn();//函数声明提升到了作用域顶部
function fn(){
console.log(a);//输出undefined
var a = 1;
console.log(a); //输出1;
}
console.log(a);//输出100
简单说下js函数编译的顺序,代码执行的前一刻,会创建一个ao对象,将形参以及变量声明放到ao对象中,并赋值为undefined,然后统一实参形参,接着函数声明整体提升,预编译环节结束之后开始执行代码,所以,在第一次log ->a时当前函数作用域中的a因为变量提升导致打印出来undefined;
使用let :
let a = 100;
fn();
function fn(){
console.log(a);// Cannot access 'a' before initialization
let a = 1;
};
这时会报不能在初始化之前访问的错误,称之为let 的暂时性死区;
这里再上一段代码可以更直观的了解到其中的区别
let arr = []
for (var i = 0;i<3;i++){
arr[i] = function (){
console.log(i)
}
}
//执行arr[1]()----结果打印 3
//执行arr[2]()----结果打印 3
//执行arr[3]()----结果打印 3
//其中var i 变量提升到了全局作用域下,其arr[...1,2,3]()执行之后才去访问这个i变量的值,这个时
//候i已经因为循环被增值到了3;所以每次访问都为3
//使用let :
let arr = []
for(let i = 0;i<3;i++){
arr[i] = function (){
console.log(i)
}
}
//执行arr[1]()----结果打印 1
//执行arr[2]()----结果打印 2
//执行arr[3]()----结果打印 3
//看到这疑惑了好久,如果是这样子的话那么最终的结果应该也是3才对(产生闭包,所有值指向for块中的i)
//在这里我大胆的猜想for(let i定义时){}中做了一些隐性的操作,并且和var做了区分,在使用let定义
//条件值的时候 在{}中顶部 使用了 let k = i; 然后将以下的i全部代替为k;
继续用代码来验证:
for(let y = {i:0};y.i<3;y.i++){
arr[y.i] = function (){
console.log(y.i)
}
}
//执行arr[1]()----结果打印 3
//执行arr[2]()----结果打印 3
//执行arr[3]()----结果打印 3
// 此时for(){}顶部虽然将 y 赋值给 k 但是y现在是一个引用值类型,他们的值指向同一个地址,所以外部成功的访问到了此时y的值;