當前位置:
首頁 > 最新 > 菜雞進階路之 Debounce&LazyFunction

菜雞進階路之 Debounce&LazyFunction

題外話

上篇說到 兼容 IE 不是夢的 MVVM 框架 san,相信大家對它已經有了簡單的了解。曾經承諾會在第二篇講一講其中的奧秘, but...

引入

那麼這篇文章究竟要講什麼呢竟可以如此重要?事情源於某位程序員在曾經的某年某月某日上線的一坨很low的代碼(為了避免被開除,關鍵地方已經打碼—.—)。

這坨代碼的需求是什麼呢?當 a 節點滾動的時候,與 a 隔著很遠的 b 節點要消失,當 a 停止滾動後,b 再出現。 那麼代碼里是怎麼實現的呢?當 a 滾動的時候把 b 消失,接著判斷是否有定時器,如果有,clear 掉,然後賦值一個新的定時器給timer,定時器里呢就清理掉自己,然後把 b 展示出來。

其實使用定時器的想法是好的,成功的攔截了數次無用且高消耗的dom 操作,但每次滾動時,依舊會執行一次 hide 操作,再而那麼一坨複雜的定時器操作在代碼中出現實在不太優雅,且不便於維護。而代碼里又使用了 underscore,於是我們的主角們就要登場了。。

Debounce

Debounce的中文含義:防反跳。在 js 中呢,我們可以理解為,強制一個函數在某個過程中只執行一次,哪怕它本應該執行多次。就像上面的示例一樣,我們希望滾動時 b 消失,滾動停止後 b 再出現,如果我們不做定時器的攔截,那麼每次滾動都會去觸發這些動作,而加了攔截之後,只會在最後一次滾動結束後的500毫秒(代碼中設置了500)後去執行一次。

接下來讓我們看一下如果使用 underscore 的_.debounce 上面的代碼將如何實現。

_.debounce我們傳入了兩個參數,一個回調function,一個時間delay。其實還有第三個參數叫 immediate,表示回調 function 是在某個時間的最開始執行還是最後執行,這裡先忽略。我們看下underscore里是怎麼實現的。

_.debounce返回一個函數,即我們在滾動時不斷觸發的函數。這個函數里首先判斷了 timeout 是否存在,如果存在就把它清理掉,忽略 immediate,接著會給 timeout 賦值,_.delay里返回的就是一個定時器。而定時器所執行的 later 函數,就是去執行我們傳入的回調。wait,wait...這不就是那位程序員在代碼里費半天勁寫的定時器的邏輯嗎???啥也別說了,在此贈上那句至理名言:每多學一點知識,就少寫一行代碼

使用場景

文本輸入的keyup事件

滑鼠移動mousemove事件

DOM 元素的 resize,scroll事件

這些可以等到一個連續的事件結束後再進行響應的事件,都可以採用這種方式。

Lazy Function

通常,講完debounce一般都會再講講throttle。作為二般的情況,我們接下來說一說Lazy Function。Lazy Function即惰性函數,它的意思是:一個函數的內容,只有在它第一次被掉用的時候執行,並且在第一次調用過程中,該函數會被覆蓋為另一個按照合適方式執行的函數,這樣任何對原函數的調用都不會再走它最初的邏輯。

為什麼要說它呢,前面說過,那段很 low 的代碼里,每次滾動都要執行b的隱藏這個dom操作,這顯然是多餘的。那麼為什麼不可以利用上面所說的原理,把 b 隱藏操作當成一個函數,在第一次滾動執行之後,執行該函數,然後將該函數置空,當確認結束滾動後,再將該函數改回原來的樣子。這樣一番操作之後,利用惰性函數的原理,大大提高了性能。讓我們一起觀賞下改善後的代碼。

應用場景

應用頻繁,如上例中,滾動時在不斷觸發。如果只用一次,是體現不出他的優勢的。

固定改變,即一次改變之後,後面不會再變化。

總結

總而一句話:多讀書多看報少吃零食多睡覺,多旁聽多求教少說大話多微笑。


喜歡這篇文章嗎?立刻分享出去讓更多人知道吧!

本站內容充實豐富,博大精深,小編精選每日熱門資訊,隨時更新,點擊「搶先收到最新資訊」瀏覽吧!


請您繼續閱讀更多來自 Web手藝人 的精彩文章:

TAG:Web手藝人 |