最近面試常常碰到這樣一道題(或者相似):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
其實,核心問題,就是等待循環結束,纔去訪問i,並且訪問的是同一個i。
解決思路:兩種 改變訪問時機, 改變訪問變量。作用域
for( var i = 0; i < 5; i++){ console.log(i); }
這樣作好像沒什麼意義。get
function fun(){ for (let i = 0; i < 5; i++){ setTimeout(()=>{ console.log(i) },0); } } fun();
用let代替var來聲明變量,就能夠把變量的做用域限制在當前代碼塊中也就是{}io
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
分割線(這對以前問題的處理)
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();