當前位置:
首頁 >
前端技术
> javascript
>内容正文
javascript
JavaScript函数节流和函数防抖
生活随笔
收集整理的這篇文章主要介紹了
JavaScript函数节流和函数防抖
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
1.為什么需要函數防抖和函數節流?
- 在瀏覽器中某些計算和處理要比其他的昂貴很多。例如DOM操作比起非DOM交互需要更多的內存和CPU占用時間。連續嘗試進行過多的DOM操作可能會導致瀏覽器掛起,甚至崩潰;
- 例如當調整瀏覽器大小的時候,resize事件會連續觸發;如果在resize事件處理程序內部嘗試進行DOM操作,其高頻率的更改可能會讓瀏覽器崩潰;
- 為了繞開上面的問題,需要對該類函數進行節流;
2.什么是函數防抖和函數節流
防抖(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,(只要頁面滾動就會間隔一段時間判斷一次) |
4.如何實現
4.1 函數防抖實現
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);} }第一次調用函數,創建一個定時器,在指定的時間間隔之后運行代碼; 當第二次調用該函數時,它會清除前一次的定時器并設置另一個; 如果前一個定時器已經執行過了,這個操作就沒有任何意義; 然而,如果前一個定時器尚未執行,其實就是將其替換為一個新的定時器; 目的是只有在執行函數的請求停止了delay時間之后才執行。4.2 函數節流實現
4.2.1 利用時間戳簡單實現
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代碼
<div class="wrap"><div class="header">滾動事件:普通</div><div class="container"><div class="content"></div></div></div><div class="wrap"><div class="header">滾動事件:<strong>加了函數防抖</strong></div><div class="container"><div class="content"></div></div></div><div class="wrap"><div class="header">滾動事件:<strong>加了函數節流</strong></div><div class="container"><div class="content"></div></div></div>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);}} }效果截圖
?
6.總結
總結
以上是生活随笔為你收集整理的JavaScript函数节流和函数防抖的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: JavaScript的JSON转变函数p
- 下一篇: 外汇是什么行业类型(外汇是什么行业)