91超碰碰碰碰久久久久久综合_超碰av人澡人澡人澡人澡人掠_国产黄大片在线观看画质优化_txt小说免费全本

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

for循環 + setTimeout 結合一些示例(前端面試題)

發布時間:2020-09-19 12:37:21 來源:腳本之家 閱讀:168 作者:小蔣不素小蔣 欄目:web開發

一、背景

最近在翻看以前的老書《node.js開發指南》,恰好碰到 for 循環 + setTimeout 的經典例子,于是重新梳理了思路并記錄下。

二、寫在前面,setTimeout 和 setInterval 的執行機制

在日常編碼中,你會發現,給 setTimeout 和 setInterval 設定延遲時間往往并不準,或者干脆 setTimeout(function(){xxx},0) 也不是立馬執行(特別是有耗時代碼在前),這是因為 js 是單線程的,有一個事件隊列機制,setTimeout 和 setInterval 的回調會到了延遲時間塞入事件隊列中,排隊執行。

setTimeout :延時 delay 毫秒之后,啥也不管,直接將回調函數加入事件隊列。

setInterval :延時 delay 毫秒之后,先看看事件隊列中是否存在還沒有執行的回調函數( setInterval 的回調函數),如果存在,就不要再往事件隊列里加入回調函數了。

看下面示例:

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

結果:1 秒之后,同時輸出 5 個 5。

因為 for 循環會先執行完(同步優先于異步優先于回調),這時五個 setTimeout 的回調全部塞入了事件隊列中,然后 1 秒后一起執行了。

三、正文

接下來就是那道經典的代碼:

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

結果:5 5 5 5 5

為什么不是 1 2 3 4 5,問題出在作用域上。

因為 setTimeout 的 console.log(i); 的i是 var 定義的,所以是函數級的作用域,不屬于 for 循環體,屬于 global。等到 for 循環結束,i 已經等于 5 了,這個時候再執行 setTimeout 的五個回調函數(參考上面對事件機制的闡述),里面的 console.log(i); 的 i 去向上找作用域,只能找到 global下 的 i,即 5。所以輸出都是 5。

解決辦法:人為給 console.log(i); 創造作用域,保存i的值。

解決辦法一

for (var i = 0; i < 5; i++) { 
  (function(i){   //立刻執行函數
    setTimeout(function (){
      console.log(i); 
     },1000); 
  })(i); 
}

這里用到立刻執行函數。這樣 console.log(i); 中的i就保存在每一次循環生成的立刻執行函數中的作用域里了。

解決辦法二

for (let i = 0; i < 5; i++) {   //let 代替 var
  setTimeout(function (){
    console.log(i); 
   },1000); 
}

let 為代碼塊的作用域,所以每一次 for 循環,console.log(i); 都引用到 for 代碼塊作用域下的i,因為這樣被引用,所以 for 循環結束后,這些作用域在 setTimeout 未執行前都不會被釋放。

四、補充

在寫示例代碼的過程中,發現一個語法點:

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

報錯:

TypeError: "callback" argument must be a function
at setTimeout (timers.js:421:11)
……

百度了下,原來 setTimeout 不支持傳帶參數的函數,可以再用一個匿名函數包裝下它吧,見下面代碼:

function a(i){ 
  console.log(i);  
}
for (var i = 0; i < 5; i++) { 
  setTimeout(function(){ //用匿名函數包裝
    a(i);
  },1000); 
} 

總結

以上所述是小編給大家介紹的for循環 + setTimeout 結合一些示例(前端面試題),希望對大家有所幫助,如果大家有任何疑問請給我留言,小編會及時回復大家的。在此也非常感謝大家對億速云網站的支持!

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

阳高县| 乌拉特后旗| 彰化县| 开远市| 桃园县| 福泉市| 建宁县| 涞源县| 绥宁县| 新巴尔虎左旗| 托克托县| 关岭| 嵊州市| 南充市| 内黄县| 黄大仙区| 滕州市| 泸定县| 旅游| 溧阳市| 蕉岭县| 平果县| 沾益县| 若尔盖县| 盐边县| 庄浪县| 华蓥市| 筠连县| 阳东县| 濉溪县| 孙吴县| 左云县| 黄石市| 铜山县| 台湾省| 江陵县| 大兴区| 吉首市| 四平市| 中西区| 望奎县|