在ES6 的規範中,多了兩個聲明變量的關鍵字: let 和const。初次學習的時候,只記住了 let 聲明的變量只在for 的循環體中有效,循環結束後 變量就消失了, 同時const 也能夠在for 循環中聲明變量,可是不能用於 常規的for 循環中。所謂的常規for 循環就是for(let i =0; i < 10; i++) 的格式。今天重讀了一遍Understanding ECMAScript 6, 算是明白了。json
當咱們在使用for 循環的時候,每一次的迭代都會從新聲明一個變量。像for(let i = 0; i < 10; i++); 這樣使用時,i 變量聲明瞭10次,只不過每一次迭代改i 賦值不同而已,而且變量只在循環體中使用。 咱們能夠這樣理解: 第一次迭代的使用,聲明瞭一個變量i, 賦值爲0, 0 < 10, 而後執行循環體,執行完以後i++ 變成了1. 這一次迭代就結束了,這個i 的使命就完成了。而後進行第二次迭代,這時從新聲明一個變量i, 不過此次給他賦值爲1,1 < 10 繼續執行循環體,而後加1. 此次迭代又結束了,這個i 也完成了使命,消失了。第三次迭代進行一樣的操做,聲明一個全新的變量i,執行循環體之類的,直達整個循環結束。數組
對於for 循環來講,每一次的迭代都是從新聲明一個全新的變量i,只是賦的值是上一次迭代完成時的值,這樣的話,循環體內獲取到的i, 每次也都是全新的變量i,而不是像使用 var 聲明時獲得的是全局變量,而且,每一次迭代完成後,i 變量就消失了。舉個簡單的例子,你們一看就能明白。學習
let funs = []; // 使用var 聲明循環變量i for (var i = 0; i < 10; i++) { funs.push(function(){ console.log(i); }) } // funs.forEach(item => item()); // 輸出10個10 // 改成使用let 聲明循環變量 let funss = []; for (let i = 0; i < 10; i++) { funss.push(function(){ console.log(i); }) } funss.forEach(item => item()); // 輸出0, 1, 2, 3, 4, 5, 6, 7, 8, 9
除了常規的for 循環以外,還有for-in 和for-of 操做, 原理都是同樣的,他們每一次的迭代都是從新聲明一個全新的迭代對象,而不是給原來聲明的迭代對象賦新值, 循環體內獲取到的都是當前迭代對象的值。spa
let funcs = []; let arr = [1, 2, 3]; // for-in 循環, 數組是不建議使用for-in ,這裏只是簡單的演示 for (let key in arr) { funcs.push(function() { console.log(key); }); } funcs.forEach(function(func) { func(); // 輸出0, 1, 2 }); // 使用for-of funcs = []; for (let key of arr) { funcs.push(function() { console.log(key); }); } funcs.forEach(function(func) { func(); // 輸出1, 2,3 });
如今看一下const, const 也可使用在for循環中。最簡單的就是把上面的三個for 循環中的let 都轉換爲const. for (const i = 0; i < 10; i++) {}; for (const key of arr) {} , for (const key in arr) {} . 這時你會發現第一種常規for 循環報錯了。看一下第一次迭代就知道了。聲明瞭一個 變量i, 賦值爲0。 但這裏使用const, 也就意味着i 在聲明以後,就不能再改變了。好了,0 < 10, 執行循環體,而後 加1,報錯了,i 不能變化了。一次迭代都沒有走完,就報錯了,說明,在使用常規for 循環時, const 不能用來聲明變量。code
再來看一下,for-of, for-in, 沒有問題,由於每一次的迭代都會聲明一個全新的key, 全部的賦值都是給一個新的變量賦值,而沒有改變原來的值。那使用let 和 const 有什麼區別嗎? 固然有了,仍是在於const 聲明的變量不能從新賦值了,因此若是for-in 或for- of 中使用const 聲明瞭變量( 如key), 循環體中,就不能給key 賦新值了,若是使用let ,那就無所謂了,想幹什麼就幹什麼。只不過for-in 或for-of 中,咱們不多改變key 值,因此他們在實際使用時就沒有什麼區別了。對象
這裏再簡單說一下const. 當聲明一個變量時,稱之爲binding(綁定)。在一個做用域中聲明變量的時候,至關於這個變量綁定到了該做用域中,對於const 聲明的變量來講,它的綁定更近了一步,直接綁定到一個值上。const name = "sam"; 變量name 直接綁定了一個值"sam"; 若是再更改這個綁定,就報錯了。那麼怎麼纔算更改綁定呢?就是從新賦值。name ="json" 報錯了。若是name 剛開始綁定的是一個對象呢? const name = {a: 'b"}, 仍是同樣,從新賦值就會報錯,name={} 報錯。但若是改變對象的值,則沒有問題 name. a = "c"; 由於沒有改變綁定。name 綁定到一個對象,就至關於咱們的地址 對應的一個真實的建築物 . const 聲明瞭一個變量,就至關於寫了一個地址,好比,北京市東城區長安街, 綁定到一個對象上,那就是故宮了。北京市東城區長安街 綁定到了天安門對象上。那若是更改綁定,就意味着北京市東城區長安街 綁定到別的地方了,好比長城,那誰受得了,原本是想看故宮的,忽然變成遊長城了。但若是改變故宮呢? 好比故宮今天安排了特別的文藝演出,沒有問題啊?故宮還在那地方,按照地址仍是到故宮了。blog