一、概念
函數(shù)節(jié)流和函數(shù)防抖,兩者都是優(yōu)化高頻率執(zhí)行js代碼的一種手段邦马。
舊款電視機(jī)的工作原理,就是一行行得掃描出色彩到屏幕上宴卖,然后組成一張張圖片滋将。由于肉眼只能分辨出一定頻率的變化,當(dāng)高頻率的掃描症昏,人類是感覺不出來的随闽。反而形成一種視覺效果,就是一張圖肝谭。就像高速旋轉(zhuǎn)的風(fēng)扇掘宪,你看不到扇葉,只看到了一個圓一樣攘烛。
同理魏滚,可以類推到j(luò)s代碼。在一定時間內(nèi)坟漱,代碼執(zhí)行的次數(shù)不一定要非常多鼠次。達(dá)到一定頻率就足夠了。因?yàn)榕艿迷蕉啵瑤淼男Ч彩且粯有瓤堋5共蝗绯婶妫裫s代碼的執(zhí)行次數(shù)控制在合理的范圍。既能節(jié)省瀏覽器CPU資源赦役,又能讓頁面瀏覽更加順暢麻敌,不會因?yàn)閖s的執(zhí)行而發(fā)生卡頓。這就是函數(shù)節(jié)流和函數(shù)防抖要做的事掂摔。
函數(shù)防抖(debounce)
當(dāng)調(diào)用動作過n毫秒后庸论,才會執(zhí)行該動作,若在這n毫秒內(nèi)又調(diào)用此動作則將重新計算執(zhí)行時間
函數(shù)節(jié)流(throttle)
預(yù)先設(shè)定一個執(zhí)行周期棒呛,當(dāng)調(diào)用動作的時刻大于等于執(zhí)行周期則執(zhí)行該動作,然后進(jìn)入下一個新周期
函數(shù)節(jié)流是指一定時間內(nèi)js方法只跑一次域携。比如人的眨眼睛簇秒,就是一定時間內(nèi)眨一次。這是函數(shù)節(jié)流最形象的解釋秀鞭。
函數(shù)防抖是指頻繁觸發(fā)的情況下趋观,只有足夠的空閑時間,才執(zhí)行代碼一次锋边。比如生活中的坐公交皱坛,就是一定時間內(nèi),如果有人陸續(xù)刷卡上車豆巨,司機(jī)就不會開車剩辟。只有別人沒刷卡了,司機(jī)才開車往扔。
二贩猎、函數(shù)節(jié)流
函數(shù)節(jié)流應(yīng)用的實(shí)際場景,多數(shù)在監(jiān)聽頁面元素滾動事件的時候會用到萍膛。因?yàn)闈L動事件吭服,是一個高頻觸發(fā)的事件。以下是監(jiān)聽頁面元素滾動的示例代碼
函數(shù)節(jié)流的要點(diǎn)是蝗罗,聲明一個變量當(dāng)標(biāo)志位艇棕,記錄當(dāng)前代碼是否在執(zhí)行。
?如果空閑串塑,則可以正常觸發(fā)方法執(zhí)行沼琉。
?如果代碼正在執(zhí)行,則取消這次方法執(zhí)行拟赊,直接return
這個方法的作用是監(jiān)聽ID為throttle元素的滾動事件刺桃。
當(dāng)canRun為true,則代表現(xiàn)在的滾動處理事件是空閑的,可以使用瑟慈。
通過關(guān)卡if(!canRun)桃移,等于就拿到了通行證。然后下一步的操作就是立馬將關(guān)卡關(guān)上canRun=false葛碧。這樣借杰,其他請求執(zhí)行滾動事件的方法,就被擋回去了进泼。
接著用setTimeout規(guī)定最小的時間間隔300蔗衡,接著再執(zhí)行setTimeout方法體里面的內(nèi)容。
最后乳绕,等setTimeout里面的方法都執(zhí)行完畢绞惦,才釋放關(guān)卡canRun=true,允許下一個訪問者進(jìn)來洋措。
這個函數(shù)節(jié)流的實(shí)現(xiàn)形式济蝉,需要注意的是執(zhí)行的間隔時間是>=300ms。如果具體執(zhí)行的方法是包含callback的菠发,也可以將canRun=true這一步放到callback中王滤。
三、函數(shù)防抖
函數(shù)防抖的應(yīng)用場景滓鸠,最常見的就是用戶注冊時候的手機(jī)號碼驗(yàn)證和郵箱驗(yàn)證了雁乡。只有等用戶輸入完畢后,前端才需要檢查格式是否正確糜俗,如果不正確踱稍,再彈出提示語。以下還是以頁面元素滾動監(jiān)聽的例子
函數(shù)防抖的要點(diǎn)悠抹,也是需要一個setTimeout來輔助實(shí)現(xiàn)寞射。延遲執(zhí)行需要跑的代碼。
如果方法多次觸發(fā)锌钮,則把上次記錄的延遲執(zhí)行代碼用clearTimeout清掉桥温,重新開始。
如果計時完畢梁丘,沒有方法進(jìn)來訪問觸發(fā)侵浸,則執(zhí)行代碼。
這個方法的作用是監(jiān)聽ID為debounce元素的滾動事件
進(jìn)入滾動事件方法體的時候氛谜,做的第一件事就是清除上次未執(zhí)行的setTimeout掏觉。而setTimeout的引用id由變量timer記錄。
clearTimeout方法值漫,允許傳入無效的值澳腹。所以這里直接執(zhí)行clearTimeout即可。
然后,將需要執(zhí)行的代碼放入setTimeout中酱塔,再返回setTimeout引用給timer緩存沥邻。
如果倒計時300ms以后,還沒有新的方法觸發(fā)滾動事件羊娃,則執(zhí)行setTimeout中的代碼唐全。
函數(shù)防抖的實(shí)現(xiàn)重點(diǎn),就是巧用setTimeout做緩存池蕊玷,而且可以輕易地清除待執(zhí)行的代碼