ES6:let和var区别

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泄露成了全局变量

相关文章
相关标签/搜索