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