ES6 中的let 和 const

  1,塊級做用域。這裏想說的是,在一個塊{}中,使用const或let 聲明一個變量,這個變量將統治整個塊(consumes the entire scope),不管你在塊的什麼地方聲明這個變量。就算,你是在塊的底部聲明瞭一個變量, 可是這個變量的做用域,實際上從塊的起始部位開始算起,一直到塊的結束,存在着某種意義上的變量提高。數組

if(true) { // data 變量的做用域從這裏開始
    console.log(1); console.log(2) let data = new Date(); // data 變量的做用域在這裏開始
}

  變量存在提高,這也就意味着,咱們有可能無心地使用了後面聲明的變量,尤爲是當變量做用域外部有一個和它重名的變量時spa

let data = 1; if(true) { console.log(data); console.log(1); console.log(2) let data = new Date(); }

  運行這段代碼,報錯了。剛開始的時候,覺得第一行的data 讀取的是外部的變量data(1), 由於內部的data 變量尚未聲明。其實不是,只要在塊中聲明瞭變量,這個變量將統治整個塊。第一行的console.log 讀取的是塊中最後一行聲明的變量。儘管能讀取變量,但不能使用這個變量。在一個做用域中,在let 或const 變量聲明以前,使用這個變量,將拋出引用錯誤。可以讀取,但不能使用變量的區域就是暫存死區。在一個做用域中聲明一個變量,暫存死區,指的就是做用域開始位置,到變量聲明位置結束,引用暫存死區中的變量就會拋出引用錯誤。code

  2,const 指的是不能從新賦值, 而不是值不能改變。Constants can not be reassigned. Constants are not immutable. 對象

  必定要區分值和變量。5,false,  {name: 'sam'} 就是值。變量,是須要聲明的,let a;  它實際上是在內存中開闢了一個空間,用於保存東西。變量和值是相互獨立的。能夠聲明一個變量,不給它值,那這個變量就什麼都不能作。也能夠只寫一個值,不賦值給任何變量,但這個值只能用一次。當把一個值賦給一個變量的時候,它們有了關係,產生了綁定,變量名和值綁定到一塊兒了,這叫assigin. const 指的就是這一塊內容。值能不能改變,只關係值自己,它不關係和變量的關係。數字5,它就不能再改變了, 但對象就能夠改變。blog

   3, let 和 const 在for 循環中使用 內存

  let 聲明的變量只在for 的循環體中有效,循環結束後 變量就消失了, 同時const 也能夠在for 循環中聲明變量,可是不能用於 常規的for 循環中。所謂的常規for 循環就是for(let i =0; i < 10; i++) 的格式。作用域

  在使用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,執行循環體之類的,直達整個循環結束。it

  對於for 循環來講,每一次的迭代都是從新聲明一個全新的變量i,只是賦的值是上一次迭代完成時的值,這樣的話,循環體內獲取到的i, 每次也都是全新的變量i,而不是像使用 var 聲明時獲得的是全局變量,而且,每一次迭代完成後,i 變量就消失了。io

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 操做, 原理都是同樣的,他們每一次的迭代都是從新聲明一個全新的迭代對象,而不是給原來聲明的迭代對象賦新值, 循環體內獲取到的都是當前迭代對象的值。console

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  不能用來聲明變量。

  再來看一下,for-of, for-in, 沒有問題,由於每一次的迭代都會聲明一個全新的key, 全部的賦值都是給一個新的變量賦值,而沒有改變原來的值。那使用let 和 const 有什麼區別嗎? 固然有了,仍是在於const  聲明的變量不能從新賦值了,因此若是for-in 或for- of 中使用const 聲明瞭變量( 如key), 循環體中,就不能給key 賦新值了,若是使用let ,那就無所謂了,想幹什麼就幹什麼。只不過for-in 或for-of 中,咱們不多改變key 值,因此他們在實際使用時就沒有什麼區別了。

相關文章
相關標籤/搜索