日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 前端技术 > javascript >内容正文

javascript

JavaScript函数节流和函数防抖

發(fā)布時間:2024/9/19 javascript 54 豆豆
生活随笔 收集整理的這篇文章主要介紹了 JavaScript函数节流和函数防抖 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

1.為什么需要函數(shù)防抖和函數(shù)節(jié)流?

  • 在瀏覽器中某些計算和處理要比其他的昂貴很多。例如DOM操作比起非DOM交互需要更多的內存和CPU占用時間。連續(xù)嘗試進行過多的DOM操作可能會導致瀏覽器掛起,甚至崩潰;
  • 例如當調整瀏覽器大小的時候,resize事件會連續(xù)觸發(fā);如果在resize事件處理程序內部嘗試進行DOM操作,其高頻率的更改可能會讓瀏覽器崩潰;
  • 為了繞開上面的問題,需要對該類函數(shù)進行節(jié)流;

2.什么是函數(shù)防抖和函數(shù)節(jié)流

防抖(debounce)和節(jié)流(throttle)都是用來控制某個函數(shù)在一定時間內執(zhí)行多少次的技巧,兩者相似而又不同。
背后的基本思想是?某些代碼不可以連續(xù)重復執(zhí)行。

2.1 函數(shù)防抖 (debounce)--講究保留最后一次

如果一個事件被頻繁觸發(fā)多次,并且觸發(fā)的時間間隔過短,則防抖函數(shù)可以使得對應的事件處理函數(shù)只執(zhí)行最后觸發(fā)的一次。
函數(shù)防抖可以把多個順序的調用合并成一次。

2.2 函數(shù)節(jié)流 (throttle)--講究頻率

如果一個事件被頻繁觸發(fā)多次,節(jié)流函數(shù)可以按照固定頻率去執(zhí)行對應的事件處理方法。
函數(shù)節(jié)流保證一個事件一定時間內只執(zhí)行一次。

3.應用場景

類型場景
函數(shù)防抖1. 手機號、郵箱輸入檢測
2. 搜索框搜索輸入(只需最后一次輸入完后,再放松Ajax請求)
3. 窗口大小resize(只需窗口調整完成后,計算窗口大小,防止重復渲染)
4. 滾動事件scroll(只需執(zhí)行觸發(fā)的最后一次滾動事件的處理程序)
5. 文本輸入的驗證(連續(xù)輸入文字后發(fā)送 AJAX 請求進行驗證,(停止輸入后)驗證一次就好)
函數(shù)節(jié)流1.?DOM元素的拖拽功能實現(xiàn)(mousemove)
2. 射擊游戲的?mousedown/keydown?事件(單位時間只能發(fā)射一顆子彈)
3. 計算鼠標移動的距離(mousemove)
4. 搜索聯(lián)想(keyup)
5. 滾動事件scroll,(只要頁面滾動就會間隔一段時間判斷一次)

4.如何實現(xiàn)

4.1 函數(shù)防抖實現(xiàn)

function debounce(fn, delay, scope) {let timer = null;// 返回函數(shù)對debounce作用域形成閉包return function () {// setTimeout()中用到函數(shù)環(huán)境總是window,故需要當前環(huán)境的副本;let context = scope || this, args = arguments;// 如果事件被觸發(fā),清除timer并重新開始計時clearTimeout(timer);timer = setTimeout(function () {fn.apply(context, args);}, delay);} }第一次調用函數(shù),創(chuàng)建一個定時器,在指定的時間間隔之后運行代碼; 當?shù)诙握{用該函數(shù)時,它會清除前一次的定時器并設置另一個; 如果前一個定時器已經執(zhí)行過了,這個操作就沒有任何意義; 然而,如果前一個定時器尚未執(zhí)行,其實就是將其替換為一個新的定時器; 目的是只有在執(zhí)行函數(shù)的請求停止了delay時間之后才執(zhí)行。

4.2 函數(shù)節(jié)流實現(xiàn)

4.2.1 利用時間戳簡單實現(xiàn)

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 利用定時器簡單實現(xiàn)

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>加了函數(shù)防抖</strong></div><div class="container"><div class="content"></div></div></div><div class="wrap"><div class="header">滾動事件:<strong>加了函數(shù)節(jié)流</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('執(zhí)行滾動事件!(函數(shù)防抖) count2=', ++count2);}, THRESHOLD));els[2].addEventListener('scroll', throttle(function handle() {console.log(Date.now(),', 執(zhí)行滾動事件!(函數(shù)節(jié)流) count3=', ++count3);}, THRESHOLD));

函數(shù)防抖

// 函數(shù)防抖 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(), ", 觸發(fā)第", count++, "次滾動事件!");timer = setTimeout(function () {fn.apply(context, args);console.log(Date.now(), ", 可見只有當高頻事件停止,最后一次事件觸發(fā)的超時調用才能在delay時間后執(zhí)行!");}, delay);} }

函數(shù)節(jié)流

// 函數(shù)節(jié)流 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.總結

  • debounce和throttle均是通過減少高頻觸發(fā)事件的實際事件處理程序的執(zhí)行來提高事件處理函數(shù)運行性能的手段,并沒有實質上減少事件的觸發(fā)次數(shù)。
  • debounce可以把多個順序的調用合并成一次。
  • throttle保證一個事件一定時間內只執(zhí)行一次。
  • 總結

    以上是生活随笔為你收集整理的JavaScript函数节流和函数防抖的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。