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时,就在上一轮循环基础上进行计算)

另外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命令,他所声明的变量就绑定这个区域,不再受外部影响。

var str = 123;
if(true){
    str = 'abc';//ReferenceError
    let str;
}

代码中存在全局变量str,但是块级作用域内let又声明了一个局部变量str,导致后者绑定这个块级作用域,所以在let声明变量之前对str赋值会报错。

(function foo(x=y,y=2){
    return[x,y];
})();//报错

因为参数x默认等于另一个参数y,而此时y还没有声明,属于‘死区’。

ES5只有全局作用域和函数作用域,没有块级作用域导致一些错误的产生

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

猜你喜欢

转载自my.oschina.net/u/3787168/blog/1788826