let和var区别数组
var a = []; for(var i = 0;i<10;i++){ a[i] = function(){console.log(i);}; } a[6]();//10 var b = []; for(let j = 0;j<10;j++){ a[j] = function(){console.log(j);}; } a[5]();//5
第一个var中变量i,在全局范围内有效,因此全局只有一个变量i,每次循环i的值都会发生改变,而循环内被赋值给数组a的函数内部的console.log(i);里面的i指向的就是全局的i。全部数组a的成员里边的i都是同一个i;致使运行时输出的是最后一轮的i值也就是10;函数
第二个let中变量i,当前的i只在本轮循环中有效,因此每次循环的i其实都是一个新的变量,因此最后的输出为6.(虽然每次i都是从新声明的,可是js引擎内部会记住上一轮循环的值,初始化本轮的变量i时,就在上一轮循环基础上进行计算)code
另外for循环还有一个特别之处,就是设置循环变量的那部分是一个父做用域,而循环体内部是一个单独的子做用域。内存
for(let i = 0;i<3;i++){ let i = '123' console.log(i); } //123 //123 //123
var命令会发生_变量提高_现象,即变量能够在声明以前使用,值为undefined, 而let则会报错作用域
console.log(a);//undefined var a = 2;
"暂时性死区"(temporal dead zone,简称TDZ) 若是在区域块中存在let和const命令,这个区块对这些命令声明的变量从一开始就造成了封闭做用域。凡是在声明以前就使用这些变量就会报错。 只要块级做用域内存在let命令,他所声明的变量就绑定这个区域,再也不受外部影响。io
var str = 123; if(true){ str = 'abc';//ReferenceError let str; }
代码中存在全局变量str,可是块级做用域内let又声明了一个局部变量str,致使后者绑定这个块级做用域,因此在let声明变量以前对str赋值会报错。console
(function foo(x=y,y=2){ return[x,y]; })();//报错
由于参数x默认等于另外一个参数y,而此时y尚未声明,属于‘死区’。for循环
ES5只有全局做用域和函数做用域,没有块级做用域致使一些错误的产生function
var tmp = new Date(); function f() { console.log(tmp); if (false) { var tmp = 'hello world'; } } f(); // undefined
变量提高致使内层的tmp变量覆盖了外层的tmp变量。基础
var s = 'hello'; for (var i = 0; i < s.length; i++) { console.log(s[i]); } console.log(i); // 5
i泄露成了全局变量