国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 編程 > JavaScript > 正文

for循環(huán) + setTimeout 結(jié)合一些示例(前端面試題)

2019-11-19 15:36:26
字體:
供稿:網(wǎng)友

一、背景

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

二、寫在前面,setTimeout 和 setInterval 的執(zhí)行機(jī)制

在日常編碼中,你會發(fā)現(xiàn),給 setTimeout 和 setInterval 設(shè)定延遲時(shí)間往往并不準(zhǔn),或者干脆 setTimeout(function(){xxx},0) 也不是立馬執(zhí)行(特別是有耗時(shí)代碼在前),這是因?yàn)?js 是單線程的,有一個事件隊(duì)列機(jī)制,setTimeout 和 setInterval 的回調(diào)會到了延遲時(shí)間塞入事件隊(duì)列中,排隊(duì)執(zhí)行。

setTimeout :延時(shí) delay 毫秒之后,啥也不管,直接將回調(diào)函數(shù)加入事件隊(duì)列。

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

看下面示例:

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

結(jié)果:1 秒之后,同時(shí)輸出 5 個 5。

因?yàn)?for 循環(huán)會先執(zhí)行完(同步優(yōu)先于異步優(yōu)先于回調(diào)),這時(shí)五個 setTimeout 的回調(diào)全部塞入了事件隊(duì)列中,然后 1 秒后一起執(zhí)行了。

三、正文

接下來就是那道經(jīng)典的代碼:

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

結(jié)果:5 5 5 5 5

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

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

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

解決辦法一

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

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

解決辦法二

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

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

四、補(bǔ)充

在寫示例代碼的過程中,發(fā)現(xiàn)一個語法點(diǎn):

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

報(bào)錯:

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

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

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

總結(jié)

以上所述是小編給大家介紹的for循環(huán) + setTimeout 結(jié)合一些示例(前端面試題),希望對大家有所幫助,如果大家有任何疑問請給我留言,小編會及時(shí)回復(fù)大家的。在此也非常感謝大家對武林網(wǎng)網(wǎng)站的支持!

發(fā)表評論 共有條評論
用戶名: 密碼:
驗(yàn)證碼: 匿名發(fā)表
主站蜘蛛池模板: 中宁县| 藁城市| 盱眙县| 大连市| 汉寿县| 凌海市| 龙口市| 梧州市| 芜湖市| 通江县| 五峰| 荣成市| 浪卡子县| 荔浦县| 蕲春县| 三门县| 全南县| 莱芜市| 同心县| 安顺市| 满洲里市| 浪卡子县| 马鞍山市| 垫江县| 永州市| 海伦市| 苍溪县| 延吉市| 衢州市| 峨边| 四川省| 将乐县| 保靖县| 石门县| 杭锦旗| 武邑县| 英超| 太和县| 安龙县| 神农架林区| 翼城县|