記一次面試

關於一道常常碰到的面試題

最近面試常常碰到這樣一道題(或者相似):ps.由於我阿姨不會就詳細分析吧。es6

var btns = document.getElementsByClassName('btn');
    for(let i = 0; i < btns.length; i++){
        btn[i].onclick = function(){
            console.log(i)
        }
    }

這個以前說過,由於面試的時候,說了主要看閉包。因此也沒有多想。面試

function fun(){
    for (var i = 0; i < 5; i++){
        setTimeout(()=>{
            console.log(i)
        },0); 
    }
}
fun();

問題

其實,經過分析就不難看出,核心點問題都是, 在一個循環內,延時打印循環變量。 全部的結果同樣。promise

問題分析

由於js的變量有提高做用,因此能夠將程序改爲成更加直觀的形式。閉包

var i = 0; 
function fun(){
    while (i < 5){
        setTimeout(()=>{
            console.log(i) // 這裏訪問的i 都是 以前定義的 i
        },1000); 
        i++;       // 這裏訪問的i 也是 以前定義的 i
    }
}
fun();

咱們改爲程序以後,就能夠看到了。 打印語句的i,由於都是在等待i變換以後,取i值打印, 因此結果同樣。函數

問題緣由

這裏產生問題的緣由在於:code

  1. for語句不會像其餘語言具備塊級做用域(也是js變量聲明提高)。
  2. 全部的訪問循環變量的值,都是延時訪問了。
  3. 訪問的i都指向同一個i。

解決方法

其實,核心問題,就是等待循環結束,纔去訪問i,並且訪問的是同一個i。
解決思路:兩種 改變訪問時機, 改變訪問變量。作用域

在改變以前訪問i。

for( var i = 0; i < 5; i++){
    console.log(i);
}

這樣作好像沒什麼意義。get

爲每一語句保存一個i值

  1. 讓for語句具備塊級做用域
    這是es6的語法規則: 使用let. (這是最簡單的一種形式)
function fun(){
    for (let i = 0; i < 5; i++){
        setTimeout(()=>{
            console.log(i)
        },0); 
    }
}
fun();

用let代替var來聲明變量,就能夠把變量的做用域限制在當前代碼塊中也就是{}io

  1. 使用閉包
    函數是具備本身的做用域的。在es6以前,都是使用閉包來實現塊做用域
function fun(){
    for (var i = 0; i < 5; i++){
        setTimeout((function(i_){
            return function(){
                console.log(i_)
            }
        })(i),0); 
    }
}
fun();

其實, 也就是用 當即執行函數參數i_ 來保存 i 值 。 固然你也能夠把i_寫成i。console


分割線(這對以前問題的處理)

  1. 使用setTime調用時候能夠傳遞參數的特性。
    難道以前面試問個人是這麼作?
function fun(){
    for (var i = 0; i < 5; i++){
        var promise = new Promise(function(resolve, reject){
            setTimeout(resolve,1000,i); 
        }); // 這個是當即執行
        promise.then(function(value){  // 回調執行
            console.log(value);
        })
    }
}
fun();

下面代碼也能夠實現,其實,你就會發現, 這是由於 setTimeout 函數 能夠調用給函數傳遞參數的緣由, 。

function fun(){
    for (var i = 0; i < 5; i++){
        setTimeout((i)=>{
            console.log(i)
        },0,i); 
    }
}
fun();
相關文章
相關標籤/搜索