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

相關文章
相關標籤/搜索