摘要:為什么需要函數防抖和函數節流在瀏覽器中某些計算和處理要比其他的昂貴很多。函數防抖如果一個事件被頻繁觸發多次,并且觸發的時間間隔過短,則防抖函數可以使得對應的事件處理函數只執行最后觸發的一次。函數防抖可以把多個順序的調用合并成一次。
1.為什么需要函數防抖和函數節流?
2.什么是函數防抖和函數節流在瀏覽器中某些計算和處理要比其他的昂貴很多。例如DOM操作比起非DOM交互需要更多的內存和CPU占用時間。連續嘗試進行過多的DOM操作可能會導致瀏覽器掛起,甚至崩潰;
例如當調整瀏覽器大小的時候,resize事件會連續觸發;如果在resize事件處理程序內部嘗試進行DOM操作,其高頻率的更改可能會讓瀏覽器崩潰;
為了繞開上面的問題,需要對該類函數進行節流;
防抖(debounce)和節流(throttle)都是用來控制某個函數在一定時間內執行多少次的技巧,兩者相似而又不同。2.1 函數防抖 (debounce)
背后的基本思想是某些代碼不可以在沒有間斷的情況下連續重復執行。
如果一個事件被頻繁觸發多次,并且觸發的時間間隔過短,則防抖函數可以使得對應的事件處理函數只執行最后觸發的一次。2.2 函數節流 (throttle)
函數防抖可以把多個順序的調用合并成一次。
如果一個事件被頻繁觸發多次,節流函數可以按照固定頻率去執行對應的事件處理方法。3.應用場景
函數節流保證一個事件一定時間內只執行一次。
類型 | 場景 |
---|---|
函數防抖 |
1. 手機號、郵箱輸入檢測 2. 搜索框搜索輸入(只需最后一次輸入完后,再放松Ajax請求) 3. 窗口大小resize(只需窗口調整完成后,計算窗口大小,防止重復渲染) 4. 滾動事件scroll(只需執行觸發的最后一次滾動事件的處理程序) 5. 文本輸入的驗證(連續輸入文字后發送 AJAX 請求進行驗證,(停止輸入后)驗證一次就好) |
函數節流 |
1. DOM元素的拖拽功能實現(mousemove) 2. 射擊游戲的 mousedown/keydown 事件(單位時間只能發射一顆子彈) 3. 計算鼠標移動的距離(mousemove) 4. 搜索聯想(keyup) 5. 滾動事件scroll,(只要頁面滾動就會間隔一段時間判斷一次) |
function debounce(fn, delay, scope) { let timer = null; // 返回函數對debounce作用域形成閉包 return function () { // setTimeout()中用到函數環境總是window,故需要當前環境的副本; let context = scope || this, args = arguments; // 如果事件被觸發,清除timer并重新開始計時 clearTimeout(timer); timer = setTimeout(function () { fn.apply(context, args); }, delay); } }
4.2 函數節流實現 4.2.1 利用時間戳簡單實現
代碼解讀
第一次調用函數,創建一個定時器,在指定的時間間隔之后運行代碼;
當第二次調用該函數時,它會清除前一次的定時器并設置另一個;
如果前一個定時器已經執行過了,這個操作就沒有任何意義;
然而,如果前一個定時器尚未執行,其實就是將其替換為一個新的定時器;
目的是只有在執行函數的請求停止了delay時間之后才執行。
function throttle(fn, threshold, scope) { let timer; let prev = Date.now(); return function () { let context = scope || this, args = arguments; let now = Date.now(); if (now - prev > threshold) { prev = now; fn.apply(context, args); } } }4.2.2 利用定時器簡單實現
function throttle2(fn, threshold, scope) { let timer; return function () { let context = scope || this, args = arguments; if (!timer) { timer = setTimeout(function () { fn.apply(context, args); timer = null; }, threshold); } } }5 舉例(scroll事件) CSS代碼
.wrap { width: 200px; height: 330px; margin: 50px; margin-top: 200px; position: relative; float: left; background-color: yellow; } .header{ width: 100%; height: 30px; background-color: #a8d4f4; text-align: center; line-height: 30px; } .container { background-color: pink; box-sizing: content-box; width: 200px; height: 300px; overflow: scroll; position: relative; } .content { width: 140px; height: 800px; margin: auto; background-color: #14ffb2; }HTML代碼
JS代碼滾動事件:普通滾動事件:加了函數防抖滾動事件:加了函數節流
let els = document.getElementsByClassName("container"); let count1 = 0,count2 = 0,count3 = 0; const THRESHOLD = 200; els[0].addEventListener("scroll", function handle() { console.log("普通滾動事件!count1=", ++count1); }); els[1].addEventListener("scroll", debounce(function handle() { console.log("執行滾動事件!(函數防抖) count2=", ++count2); }, THRESHOLD)); els[2].addEventListener("scroll", throttle(function handle() { console.log(Date.now(),", 執行滾動事件!(函數節流) count3=", ++count3); }, THRESHOLD));
// 函數防抖 function debounce(fn, delay, scope) { let timer = null; let count = 1; return function () { let context = scope || this, args = arguments; clearTimeout(timer); console.log(Date.now(), ", 觸發第", count++, "次滾動事件!"); timer = setTimeout(function () { fn.apply(context, args); console.log(Date.now(), ", 可見只有當高頻事件停止,最后一次事件觸發的超時調用才能在delay時間后執行!"); }, delay); } }
// 函數節流 function throttle(fn, threshold, scope) { let timer; let prev = Date.now(); return function () { let context = scope || this, args = arguments; let now = Date.now(); if (now - prev > threshold) { prev = now; fn.apply(context, args); } } }效果截圖
debounce和throttle均是通過減少高頻觸發事件的實際事件處理程序的執行來提高事件處理函數運行性能的手段,并沒有實質上減少事件的觸發次數。
debounce可以把多個順序的調用合并成一次。
throttle保證一個事件一定時間內只執行一次。
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://m.specialneedsforspecialkids.com/yun/99591.html
摘要:若時間差大于間隔時間,則立刻執行一次函數。不同點函數防抖,在一段連續操作結束后,處理回調,利用和實現。函數防抖關注一定時間連續觸發的事件只在最后執行一次,而函數節流側重于一段時間內只執行一次。 原博客地址,歡迎star 函數防抖和節流 函數防抖和函數節流:優化高頻率執行js代碼的一種手段,js中的一些事件如瀏覽器的resize、scroll,鼠標的mousemove、mouseover...
摘要:目的都是為了降低回調函數執行頻率,節省計算機資源,優化性能,提升用戶體驗。函數防抖事件頻繁觸發的情況下,只有經過足夠的空閑時間,才執行代碼一次。 函數節流和函數防抖的對比分析 一、前言 前端開發中,函數節流(throttle) 和 函數防抖(debounce) 作為常用的性能優化方法,兩者都是用于優化高頻率執行 js 代碼的手段,那具體它們有什么異同點呢?有對這兩個概念不太了解的小伙伴...
摘要:文件為函數要傳入的參數返回事件處理函數添加事件監聽節流函數一般用于事件的情況較多,因為這些事件的觸發是連續性的,需要在一個時間間隔內只觸發一次。 showImg(https://segmentfault.com/img/remote/1460000018998747); 閱讀原文 前言 在前端開發當中我們經常會綁定一些事件觸發的某些程序執行,有時這些事件會連續觸發,如瀏覽器窗口 s...
摘要:此時需要采用防抖和節流的方式來減少調用頻率,同時不影響原來效果。函數防抖當持續觸發事件時,一段時間段內沒有再觸發事件,事件處理函數才會執行一次,如果設定的時間到來之前就觸發了事件,延時重新開始。 js 防抖 節流 JavaScript 實際工作中,通過監聽某些事件,如scroll事件檢測滾動位置,根據滾動位置顯示返回頂部按鈕;如resize事件,對某些自適應頁面調整DOM的渲染;如ke...
摘要:文章來源詳談防抖和節流輕松理解函數節流和函數防抖函數防抖和節流好啦,今天的小菊花課堂之的防抖與節流的內容就告一段落啦,感各位能耐心看到這里。 前言 陸游有一首《冬夜讀書示子聿》——古人學問無遺力,少壯工夫老始成。紙上得來終覺淺,絕知此事要躬行。,其中的意思想必大家都能明白,在學習或工作中,不斷的印證著這首詩的內涵。所以,又有了此篇小菊花文章。 詳解 在前端開發中,我們經常會碰到一些會持...
閱讀 1322·2021-11-16 11:45
閱讀 2242·2021-11-02 14:40
閱讀 3886·2021-09-24 10:25
閱讀 3032·2019-08-30 12:45
閱讀 1262·2019-08-29 18:39
閱讀 2477·2019-08-29 12:32
閱讀 1611·2019-08-26 10:45
閱讀 1925·2019-08-23 17:01