首頁  >  問答  >  主體

javascript - 關於let宣告的變量,在這段程式碼中是如何運作的?

一段用於增強顯示的程式碼如下:

for(var i=0;i<aLi.length;i++){
    var oldColor=null;
    aLi[i].onmouseover=function(){
        oldColor=this.style.backgroundColor;
        this.style.backgroundColor="#ccc";
    }
    aLi[i].onmouseout=function(){
        this.style.backgroundColor=oldColor;
    }
}

在這裡this.style是不能用aLi[i].style代替的,因為i早已循環完畢;
但如果i的值用let聲明,就完全不一樣,事件函數內也能準確調用i的值:

for(let i=0;i<aLi.length;i++){
    var oldColor=null;
    aLi[i].onmouseover=function(){
        oldColor=this.style.backgroundColor;
        consol.log(i);
        aLi[i].style.backgroundColor="#ccc";
    }
    aLi[i].onmouseout=function(){
        this.style.backgroundColor=oldColor;
    }
}

事件函數觸發時,不應該是報錯找不到i麼?為什麼能成功運行

过去多啦不再A梦过去多啦不再A梦2708 天前781

全部回覆(1)我來回復

  • 世界只因有你

    世界只因有你2017-06-12 09:30:06

    ES6 新增了let指令,用來宣告變數。它的用法類似var,但是所宣告的變量,只在let指令所在的程式碼區塊內有效。

        {
          let a = 10;
          var b = 1;
        }
        a // ReferenceError: a is not defined.
        b // 1

    上面程式碼在程式碼區塊之中,分別用let和var宣告了兩個變數。然後在程式碼區塊之外呼叫這兩個變量,結果let宣告的變數報錯,var宣告的變數回傳了正確的值。這表明,let聲明的變數只在它所在的程式碼區塊有效。

    for迴圈的計數器,就很適合使用let指令。

    for (let i = 0; i < 10; i++) {
      // ...
    }
    
    console.log(i);
    // ReferenceError: i is not defined

    上面程式碼中,計數器i只在for迴圈體內有效,在循環體外引用就會報錯。

    下面的程式碼如果使用var,最後輸出的是10。

    var a = [];
    for (var i = 0; i < 10; i++) {
      a[i] = function () {
        console.log(i);
      };
    }
    a[6](); // 10

    上面程式碼中,變數i是var指令宣告的,在全域範圍內都有效,所以全域只有一個變數i。每一次循環,變數i的值都會改變,而循環內被賦給數組a的函數內部的console.log(i),裡面的i指向的就是全域的i。也就是說,所有陣列a的成員裡面的i,指向的都是同一個i,導致運行時輸出的是最後一輪的i的值,也就是10。

    如果使用let,宣告的變數只在區塊級作用域內有效,最後輸出的是6。

    var a = [];
    for (let i = 0; i < 10; i++) {
      a[i] = function () {
        console.log(i);
      };
    }
    a[6](); // 6

    上面程式碼中,變數i是let宣告的,目前的i只在本輪循環有效,所以每一次迴圈的i其實都是一個新的變量,所以最後輸出的是6。你可能會問,如果每一輪循環的變數i都是重新聲明的,那它怎麼知道上一輪循環的值,從而計算出本輪循環的值?這是因為 JavaScript 引擎內部會記住上一輪循環的值,初始化本輪的變數i時,就在上一輪循環的基礎上進行計算。

    另外,for迴圈還有一個特別之處,就是設定迴圈變數的部分就是一個父作用域,而迴圈體內部是一個單獨的子作用域。

    for (let i = 0; i < 3; i++) {
      let i = 'abc';
      console.log(i);
    }
    // abc
    // abc
    // abc

    上面程式碼正確運行,輸出了3次abc。這表示函數內部的變數i與迴圈變數i不在同一個作用域,有各自單獨的作用域。

    回覆
    0
  • 取消回覆