摘要:每次鼠標(biāo)移動(dòng)都是這樣的處理過(guò)程,直到鼠標(biāo)不再移動(dòng)一秒鐘后,定時(shí)器中的函數(shù)才被使用。
函數(shù)節(jié)流的原理
函數(shù)節(jié)流,就是對(duì)會(huì)頻繁觸發(fā)的函數(shù)事件做一些限制,讓這些函數(shù)可以在每隔一定的時(shí)間或者每次滿足一定的條件下再觸發(fā)。一般我們會(huì)給他起一個(gè)名字throttle。也就是節(jié)流的意思。一般這樣的函數(shù)有 resize事件、ontouchmove事件等。
舉個(gè)簡(jiǎn)單的例子
測(cè)試函數(shù)節(jié)流
上面的代碼就是簡(jiǎn)單的渲染出來(lái)一個(gè)div 然后給這個(gè)div綁定了一個(gè)鼠標(biāo)移動(dòng)事件。但是我們?cè)趯?shí)際情況下,這種體驗(yàn)是不好的,因?yàn)檫@個(gè)事件會(huì)被十分頻繁的觸發(fā)。只要我們?cè)谶@個(gè)div上移動(dòng)鼠標(biāo)就會(huì)彈出這個(gè)阻塞性的事件alert,所以我們希望每隔一定時(shí)間提醒一下“您的鼠標(biāo)正在移動(dòng)”。
下面寫(xiě)一個(gè)節(jié)流的函數(shù)throttle()。
function throttle(func){ var timer; return function(){ var context = this; var args = arguments; clearTimeout(timer); timer = setTimeout(function(){ func.apply(context,args); },1000); } }
然后我們修改一下頁(yè)面上的代碼:
測(cè)試函數(shù)節(jié)流
下面我仔細(xì)解釋一下這個(gè)節(jié)流函數(shù)。
函數(shù)利用閉包的形式存儲(chǔ)了一個(gè)timer定時(shí)器變量,說(shuō)實(shí)話我剛開(kāi)始看別人在寫(xiě)這個(gè)節(jié)流函數(shù)的時(shí)候,也是不太容易懂,只是馬馬虎虎覺(jué)得是這樣的,直到我親自實(shí)現(xiàn)一遍,才明白。在這里建議親自動(dòng)手,豐衣足食~~
這個(gè)timer變量當(dāng)然也可以寫(xiě)在全局作用域中,但是可能會(huì)跟全局作用域中的變量產(chǎn)生沖突,所以在這里用閉包的形式來(lái)提供,防止它污染全局作用域。(看好多人在這里用“污染”,我想可能是如果有很多像timer這樣的變量都放在全局作用域中,到時(shí)候肯定容易與在全局作用域中常用的變量混淆。因?yàn)樗吘怪皇窃谶@個(gè)節(jié)流函數(shù)做定時(shí)器使用)。
然后就是throttle函數(shù)返回的函數(shù)了。在這個(gè)函數(shù)中,要保存好傳進(jìn)來(lái)的執(zhí)行上下文this,和參數(shù)arguments。應(yīng)為我們要注意的是setTimeout()函數(shù)中作用域是全局的,也就是setTimeout中的this指的是window,在這里這個(gè)執(zhí)行上下文其實(shí)就是container對(duì)象,傳入的參數(shù)就是鼠標(biāo)移動(dòng)這個(gè)事件的所有信息我們將這個(gè)container這個(gè)對(duì)象的鼠標(biāo)移動(dòng)事件函數(shù)重寫(xiě)成alertSomething這個(gè)函數(shù)。同時(shí)鼠標(biāo)移動(dòng)事件的信息也作為參數(shù)傳入進(jìn)去這一點(diǎn)也是我打印出他的相應(yīng)信息后才恍然大悟,可能平時(shí)我們會(huì)理所當(dāng)然的知道就是這樣子的,但是為什么會(huì)這樣子呢,我們知道了alertSomething這個(gè)函數(shù)的參數(shù)和執(zhí)行上下文是怎么傳進(jìn)去的,那直接調(diào)用elementobj.onmousemove=function(){xxxxxx}這個(gè)函數(shù)的時(shí)候,上下文和參數(shù)是怎么傳入進(jìn)去的也應(yīng)該是這樣的原理吧。這是我的個(gè)人理解。
明白了上面的基本原理,我們?cè)偈崂硪幌鹿?jié)流函數(shù)發(fā)揮作用的過(guò)程:第一次調(diào)用這個(gè)節(jié)流函數(shù)的時(shí)候也就是第一次觸發(fā)鼠標(biāo)移動(dòng)事件的時(shí)候,timer是沒(méi)有的,所以clearTimeout(timer)清理的定時(shí)器也是沒(méi)有的,但是等第二次觸發(fā)鼠標(biāo)移動(dòng)事件的時(shí)候,鼠標(biāo)移動(dòng)事件的處理函數(shù)就是一直是throttle返回的函數(shù)了。首先會(huì)清理掉上次調(diào)用的時(shí)候的定時(shí)器,然后重新設(shè)置一個(gè)定時(shí)器。每次鼠標(biāo)移動(dòng)都是這樣的處理過(guò)程,直到鼠標(biāo)不再移動(dòng)一秒鐘后,定時(shí)器中的函數(shù)才被使用。
總之仔仔細(xì)細(xì)理解一下這個(gè)過(guò)程感覺(jué)真好!
但是如果我們需要自定義延遲的事件的話怎么辦呢,下面我們可以再改進(jìn)一下:
function throttle(func,delay){ var timer; return function(){ var context = this; var args = arguments; clearTimeout(timer); timer = setTimeout(function(){ func.apply(context,args); },delay); } } function dealMouseMove(){ alert("您的鼠標(biāo)正在移動(dòng)"); }; document.getElementById("container").onmousemove = throttle(dealMouseMove,500);在這里感謝 Toobug 和 flowmemo 兩位大神的指正,上面函數(shù)的功能更應(yīng)該稱(chēng)之為debounce,也即是消除抖動(dòng)的意思。前端技術(shù)中常用的throttle相當(dāng)于一個(gè)頻率控制器,讓一段時(shí)間內(nèi)快速觸發(fā)很多次的事件處理程序可以只觸發(fā)一定的次數(shù), 而debounce不只是減少了觸發(fā)次數(shù),而且要滿足一定的條件下才會(huì)觸發(fā)。兩者實(shí)現(xiàn)方法都是差不多的,叫法不一樣而已,不能將兩者割裂開(kāi)來(lái)。
可以參考的相關(guān)網(wǎng)址:http://www.css88.com/archives/4648
可以參考的相關(guān)網(wǎng)址:http://www.alloyteam.com/2012/11/javascript-throttle/
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/79000.html
摘要:后續(xù)的一些輔助性?xún)?yōu)化讀者可以自己琢磨,如函數(shù)指向,返回值保存等。 原文:https://keelii.github.io/2016/06/11/javascript-throttle/ 在瀏覽器 DOM 事件里面,有一些事件會(huì)隨著用戶的操作不間斷觸發(fā)。比如:重新調(diào)整瀏覽器窗口大?。╮esize),瀏覽器頁(yè)面滾動(dòng)(scroll),鼠標(biāo)移動(dòng)(mousemove)。也就是說(shuō)用戶在觸發(fā)這些瀏覽...
摘要:寫(xiě)在前面專(zhuān)題系列是我寫(xiě)的第二個(gè)系列,第一個(gè)系列是深入系列。專(zhuān)題系列自月日發(fā)布第一篇文章,到月日發(fā)布最后一篇,感謝各位朋友的收藏點(diǎn)贊,鼓勵(lì)指正。 寫(xiě)在前面 JavaScript 專(zhuān)題系列是我寫(xiě)的第二個(gè)系列,第一個(gè)系列是 JavaScript 深入系列。 JavaScript 專(zhuān)題系列共計(jì) 20 篇,主要研究日常開(kāi)發(fā)中一些功能點(diǎn)的實(shí)現(xiàn),比如防抖、節(jié)流、去重、類(lèi)型判斷、拷貝、最值、扁平、柯里...
摘要:隆重請(qǐng)出主角防抖與節(jié)流。防抖與節(jié)流的異同相同都是防止某一時(shí)間段內(nèi),函數(shù)被頻繁調(diào)用執(zhí)行,通過(guò)時(shí)間頻率控制,減少回調(diào)函數(shù)執(zhí)行次數(shù),來(lái)實(shí)現(xiàn)相關(guān)性能優(yōu)化。參考文章分鐘理解的節(jié)流防抖及使用場(chǎng)景函數(shù)防抖和節(jié)流 showImg(https://segmentfault.com/img/bVburM8?w=800&h=600); 本篇課題,或許早已是爛大街的解讀文章。不過(guò)春招系列面試下來(lái),不少伙伴們還...
摘要:節(jié)流節(jié)流限制了一個(gè)函數(shù)可以在短時(shí)間內(nèi)被調(diào)用的次數(shù)。更新防抖防抖確保了一個(gè)函數(shù)只有在一個(gè)固定時(shí)間段內(nèi)沒(méi)有被調(diào)用過(guò)后,才會(huì)再次被調(diào)用。再換句話說(shuō)防抖會(huì)等待事件不再高頻發(fā)生,再觸發(fā)。這個(gè)網(wǎng)站很好的可視化了節(jié)流與防抖。 節(jié)流 Throttling 節(jié)流限制了一個(gè)函數(shù)可以在短時(shí)間內(nèi)被調(diào)用的次數(shù)??梢赃@樣形容:在一毫秒內(nèi)最多執(zhí)行此函數(shù) 1 次。 Throttling enforces a maxi...
閱讀 1414·2021-09-26 09:55
閱讀 1946·2019-08-30 12:45
閱讀 1098·2019-08-29 11:20
閱讀 3581·2019-08-26 11:33
閱讀 3462·2019-08-26 10:55
閱讀 1718·2019-08-23 17:54
閱讀 2413·2019-08-23 15:55
閱讀 2372·2019-08-23 14:23