你知道js當中for循環當中的bug嗎,如何解決它


本來以為for循環可以很好的解決一切問題,直到今天遇到了這段代碼,刷新了我對for循環的認識,話不多說,直接上代碼

 

var arr = [];
for(var i = 0;i<10;i++) {
arr[i] = function()
{
console.log(i)
}
}
arr[3]();

大家看上面這段代碼,我先聲明了一個空數組,然后把它放在循環里面,循環添加函數作為arr數組的數據,第一印象看到的時候,肯定不少人會毫不猶豫的說出3這個答案,

因為索引為3的時候console.log剛好是3嗎,想想差點自己都信了,但是,結果呢?

結果明顯是10,那么原因是什么呢?由於for循環中的i變量是用var聲明的,此時的 i 在全部范圍內都有效,所以每一次循環,新的i值會覆蓋舊的i值,導致最后輸出是最后一輪的i的值,當最后輸出的時候i 已經變為10了

那么,有沒有解決的辦法呢,辦法是有的,且聽我慢慢道來:

方法一:閉包

再用閉包的時候,你首先要了解什么是閉包,所謂“閉包”,指得是擁有許多變量和綁定了這些變量的環境的表達式(通常是一個函數),它可以訪問局部變量,並且在訪問的同時使局部變量的內存不被釋放。那么,怎么用閉包呢,簡單點來講,就是嵌套函數。代碼如下:

 

   var arr = [];
    for(var i = 0;i<10;i++){
        (function(val) {
            arr[i] = function() {
                console.log(val)
            }
        })(i)
    }
    arr[3]();

 

將for的循環內容方法放在一個自調用的匿名函數里面,這個時候的val是由 i 來傳遞的,此時的變量val可以被訪問,而且內存不被釋放,也就是說,val沒有覆蓋一說,所以自然而然的輸出結果是3

 

方法二:ES6當中的let

ES6現在的推行范圍不是很廣,而且許多低版本的瀏覽器無法識別ES6,所以此方法用的時候是有局限性的,建議你把瀏覽器的版本升為高版本;

好嘞,言歸正真,我們先來了解一下什么是ES6當中的let:

let全稱為代碼塊作用域,顧名思義他是作用域代碼塊的,它和var的用法相似,但是在同一個代碼快中不能出現重名的let變量;代碼如下:

 

 var arr = [];
    for(let i = 0;i<10;i++) {
        arr2[i] = function() {
            console.log(i)
        }
    }
    arr[3]();


變量i是let聲明的,當前i只在本輪循環中有效所以每次循環的i其實是一個新的變量,所以最后輸出的是3

才疏學淺,目前只發現了這兩種方法,如果有新方法或者不對的地方,請指教。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM