JavaScript函數(shù)節(jié)流概念與用法實(shí)例詳解
本文實(shí)例講述了JavaScript函數(shù)節(jié)流概念與用法。分享給大家供大家參考,具體如下:
最近在做網(wǎng)頁(yè)的時(shí)候有個(gè)需求,就是瀏覽器窗口改變的時(shí)候需要改一些頁(yè)面元素大小,于是乎很自然的想到了window的resize事件,于是乎我是這么寫(xiě)的
<!DOCTYPE html> <html> <head> <title>Throttle</title> </head> <body> <script type="text/javascript"> n=0; function resizehandler(){ console.log(new Date().getTime()); console.log(++n); } window.onresize=resizehandler; </script> </body> </html>
功能倒是實(shí)現(xiàn)了,但是我拖拽的方式改變?yōu)g覽器窗口大小的時(shí)候看了下控制臺(tái)
沒(méi)錯(cuò),簡(jiǎn)單的一個(gè)拖拽讓我的resizeHandler()方法執(zhí)行了52次,這完全不是我想要的效果,實(shí)際上我的resizeHandler()方法的代碼很復(fù)雜,甚至?xí)褂胊jax向服務(wù)器發(fā)送請(qǐng)求,要是簡(jiǎn)單的一次改變窗口大小就要調(diào)用52次這還了得
函數(shù)節(jié)流
其實(shí)我的本意只是窗口resize后頁(yè)面做一些調(diào)整就可以,而window的resize事件并不是在resize結(jié)束后才觸發(fā)的,具體則么個(gè)頻率我也不知道,但卻是在不停的調(diào)用,直到窗口大小不再變化。其實(shí)類似的機(jī)制還有鼠標(biāo)的mousemove,都是在短時(shí)間內(nèi)重復(fù)觸發(fā)。
在《JavaScript高級(jí)程序設(shè)計(jì)》中有專門(mén)應(yīng)對(duì)此問(wèn)題的函數(shù)節(jié)流
function throttle(method,context){ clearTimeout(method.tId); method.tId=setTimeout(function(){ method.call(context); },500); }
原理很簡(jiǎn)單,利用定時(shí)器,讓函數(shù)執(zhí)行延遲500毫秒,在500毫秒內(nèi)如果有函數(shù)又被調(diào)用則刪除上一次調(diào)用,這次調(diào)用500毫秒后執(zhí)行,如此往復(fù)。這樣我剛才的代碼可以改為
<script type="text/javascript"> n=0; function resizehandler(){ console.log(new Date().getTime()); console.log(++n); } function throttle(method,context){ clearTimeout(method.tId); method.tId=setTimeout(function(){ method.call(context); },500); } window.onresize=function(){ throttle(resizehandler,window); }; </script>
拖拽一下試試,果真只執(zhí)行了一次
另一種做法
網(wǎng)上還有一種函數(shù)節(jié)流方案,它是這么做的
function throttle(method,delay){ var timer=null; return function(){ var context=this, args=arguments; clearTimeout(timer); timer=setTimeout(function(){ method.apply(context,args); },delay); } }
調(diào)用一下試試,一樣的效果
<script type="text/javascript"> n=0; function resizehandler(){ console.log(new Date().getTime()); console.log(++n); } function throttle(method,delay){ var timer=null; return function(){ var context=this, args=arguments; clearTimeout(timer); timer=setTimeout(function(){ method.apply(context,args); },delay); } } window.onresize=throttle(resizehandler,500);//因?yàn)榉祷睾瘮?shù)句柄,不用包裝函數(shù)了 </script>
比較
兩種方法都是利用了setTimeout,不同的是第二種方法加入的函數(shù)延遲執(zhí)行時(shí)間,這個(gè)在第一種方案中很容易也具有此功能,加一個(gè)參數(shù)的事兒。
但第一種方案把tId設(shè)為函數(shù)的一個(gè)變量保存,而第二種創(chuàng)建了一個(gè)閉包來(lái)存儲(chǔ)。個(gè)人覺(jué)得差距不大,很喜歡第一種,簡(jiǎn)單,高效。
新需求
有一天做了個(gè)類似的東西,就像百度首頁(yè)輸入自動(dòng)提示一樣的東西,我在text上綁定keyup事件,每次鍵盤(pán)彈起的時(shí)候自動(dòng)提示,但是又不想提示那么頻繁,于是我用了上面方法,但是悲劇了,只有停止輸入等500毫秒才會(huì)提示,在輸入過(guò)程中根本就沒(méi)有提示??戳艘幌麓a,可不是嘛,只要是用戶會(huì)盲打,在500毫秒內(nèi)按一下鍵盤(pán),提示函數(shù)就會(huì)不斷被延遲,這樣只有停下來(lái)的時(shí)候才會(huì)提示,這就沒(méi)意義了。
能不能在函數(shù)節(jié)流的基礎(chǔ)上間隔固定時(shí)間就執(zhí)行一次?
小改動(dòng)
在網(wǎng)上搜了一下我們可以根據(jù)第二種寫(xiě)法(第一種為函數(shù)拓展多個(gè)變量感覺(jué)有些不好)做些改動(dòng),添加一個(gè)參數(shù)作為到固定間隔必須執(zhí)行
function throttle(method,delay,duration){ var timer=null, begin=new Date(); return function(){ var context=this, args=arguments, current=new Date();; clearTimeout(timer); if(current-begin>=duration){ method.apply(context,args); begin=current; }else{ timer=setTimeout(function(){ method.apply(context,args); },delay); } } }
這樣每次我們判斷間隔了多久,要是超過(guò)設(shè)置時(shí)間則立即執(zhí)行一次,以剛才例子試一試效果
window.onresize=throttle(resizehandler,100,200);
果真既沒(méi)有頻繁執(zhí)行也沒(méi)有就最后執(zhí)行
更多關(guān)于JavaScript相關(guān)內(nèi)容感興趣的讀者可查看本站專題:《JavaScript切換特效與技巧總結(jié)》、《JavaScript查找算法技巧總結(jié)》、《JavaScript動(dòng)畫(huà)特效與技巧匯總》、《JavaScript錯(cuò)誤與調(diào)試技巧總結(jié)》、《JavaScript數(shù)據(jù)結(jié)構(gòu)與算法技巧總結(jié)》、《JavaScript遍歷算法與技巧總結(jié)》及《JavaScript數(shù)學(xué)運(yùn)算用法總結(jié)》
希望本文所述對(duì)大家JavaScript程序設(shè)計(jì)有所幫助。
- JS函數(shù)節(jié)流和函數(shù)防抖問(wèn)題分析
- JavaScript函數(shù)節(jié)流和函數(shù)防抖之間的區(qū)別
- 淺析JavaScript 函數(shù)防抖和節(jié)流
- 詳解JS函數(shù)防抖
- 如何解決js函數(shù)防抖、節(jié)流出現(xiàn)的問(wèn)題
- JavaScript性能優(yōu)化之函數(shù)節(jié)流(throttle)與函數(shù)去抖(debounce)
- JS中setTimeout的巧妙用法前端函數(shù)節(jié)流
- 淺談JavaScript函數(shù)節(jié)流
- 如何理解JS函數(shù)防抖和函數(shù)節(jié)流
相關(guān)文章
微信小程序?qū)崿F(xiàn)頂部固定 底部分頁(yè)滾動(dòng)效果
這篇文章主要介紹了微信小程序?qū)崿F(xiàn)頂部固定底部分頁(yè)滾動(dòng)效果,本文大概給大家分享三種解決方案,每種方案給大家詳細(xì)剖析通過(guò)代碼解析哪種方案更適合,感興趣的朋友跟隨小編一起看看吧2022-10-10實(shí)用Javascript調(diào)試技巧分享(小結(jié))
這篇文章主要介紹了實(shí)用Javascript調(diào)試技巧分享(小結(jié)),小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2019-06-06bootstrap日歷插件datetimepicker使用方法
這篇文章主要為大家詳細(xì)介紹了bootstrap日歷datetimepicker插件的使用方法,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2016-12-12javascript創(chuàng)建頁(yè)面蒙板的一些知識(shí)技巧總結(jié)
javascript創(chuàng)建頁(yè)面蒙板的一些知識(shí)技巧總結(jié)...2007-08-08JavaScript實(shí)現(xiàn)簡(jiǎn)易QQ聊天界面
這篇文章主要為大家詳細(xì)介紹了JavaScript實(shí)現(xiàn)簡(jiǎn)易QQ聊天界面,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2022-07-07利用ASP發(fā)送和接收XML數(shù)據(jù)的處理方法與代碼
利用ASP發(fā)送和接收XML數(shù)據(jù)的處理方法與代碼...2007-11-11