for循环中let和var的区别MDN的let:let允许你声明一个变量、语句或表达式,其范围被限制在块级。与var关键字不同,var声明的变量只能是全局的或整个功能块。在ECMAScript2015中,let绑定不受变量提升的影响,这意味着let声明不会提升到当前执行上下文的顶部。在初始化之前在块中引用变量将导致ReferenceError(与使用var声明变量相反,后者的值为undefined)。从块的开始到let初始化过程,这个变量都处于“临时死区”。循环定义中的let作用域:循环体可以引用for语句中用let定义的变量,虽然let没有出现在花括号之间。varlist=document.getElementById("列表");for(leti=1;i<=5;i++){varitem=document.createElement("LI");item.appendChild(document.createTextNode("Item"+i));让j=我;item.onclick=function(ev){console.log("项目"+j+"被点击。");};list.appendChild(item);}在每次循环中使用letj来保持i的值,所以当i改变的时候,j不会改变。而console.log是j,即使这里的i语句改成var,结果还是一样。MDN这里的写法是多余的,去掉letj=i仍然可以达到上面的效果,只是为了方便对let的理解。其实去掉letj=i,相当于:for(leti=1;i<=5;i++){//leti=i;即i的作用域放在块级作用域中varitem=document.createElement("LI");item.appendChild(document.createTextNode("Item"+i));item.onclick=function(ev){console.log("项目"+i+"被点击。");};list.appendChild(item);}console.log(i)//UncaughtReferenceError:iisnotdefined上面代码中最后的ReferenceError说明i虽然在for循环的外层{},但实际上是绑定的在块级范围内。这与var不同。var声明的i在外层,所以成为全局变量。变量提升(提升)letx="global";(function(){console.log(x);//UncaughtReferenceError:xisnotdefinedletx='part';console.log(x)}());众所周知,letvariableshavenohoist,按照这个理解,函数中第一行log(x)应该是Global才是正确的,但是却报错了。去掉letx='part'就没有问题了,也就是说后面的语句影响了第一行的log(x).fn();函数fn(){变量x=1;console.log(x,y)vary=2}执行过程:找到所有用函数声明的变量,并在环境中“创建”这些变量。将这些变量“初始化”并“赋值”为function(){//具体内容}执行代码,即在fn()函数体中找到所有用var声明的变量,在环境中“创建”这些变量并“初始化”这些变量“是未定义的。开始执行代码,x=1,将x变量“赋值”为1,打印x=1,而y还没有赋值,所以是未定义的,如果把var改成让:找到所有声明为function的变量,在环境变量中“创建”,将这些变量“初始化”并“赋值”为function(){//具体内容}执行代码,即找到声明的所有变量withlet在fn()函数的主体中,并在环境中“创建”这些变量以开始执行代码,x=1将x变量“赋值”为1并打印x=1,但y尚未“初始化”,所以UncaughtReferenceError。这就是所谓的临时死区。
