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

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 >

函数防抖和节流

發布時間:2025/7/14 30 豆豆
生活随笔 收集整理的這篇文章主要介紹了 函数防抖和节流 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

在前端開發的過程中,我們經常會需要綁定一些持續觸發的事件,如 resize、scroll、mousemove 等等,但有些時候我們并不希望在事件持續觸發的過程中那么頻繁地去執行函數。

通常這種情況下我們怎么去解決的呢?一般來講,防抖和節流是比較好的解決方案。

讓我們先來看看在事件持續觸發的過程中頻繁執行函數是怎樣的一種情況。

html 文件中代碼如下

<div id="content" style="height:150px;line-height:150px;text-align:center; color: #fff;background-color:#ccc;font-size:80px;"></div> <script>let num = 1;let content = document.getElementById('content');function count() {content.innerHTML = num++;};content.onmousemove = count; </script> 復制代碼

在上述代碼中,div 元素綁定了 mousemove 事件,當鼠標在 div(灰色)區域中移動的時候會持續地去觸發該事件導致頻繁執行函數。效果如下

可以看到,在沒有通過其它操作的情況下,函數被頻繁地執行導致頁面上數據變化特別快。所以,接下來讓我們來看看防抖和節流是如何去解決這個問題的。

防抖(debounce)

所謂防抖,就是指觸發事件后在 n 秒內函數只能執行一次,如果在 n 秒內又觸發了事件,則會重新計算函數執行時間。

防抖函數分為非立即執行版和立即執行版。

非立即執行版:

function debounce(func, wait) {let timeout;return function () {let context = this;let args = arguments;if (timeout) clearTimeout(timeout);timeout = setTimeout(() => {func.apply(context, args)}, wait);} } 復制代碼

非立即執行版的意思是觸發事件后函數不會立即執行,而是在 n 秒后執行,如果在 n 秒內又觸發了事件,則會重新計算函數執行時間。

我們依舊使用上述綁定 mousemove 事件的例子,通過上面的防抖函數,我們可以這么使用

content.onmousemove = debounce(count,1000); 復制代碼

效果如下

可以看到,在觸發事件后函數 1 秒后才執行,而如果我在觸發事件后的 1 秒內又觸發了事件,則會重新計算函數執行時間。

上述防抖函數的代碼還需要注意的是 this 和 參數的傳遞

let context = this; let args = arguments; 復制代碼

防抖函數的代碼使用這兩行代碼來獲取 this 和 參數,是為了讓 debounce 函數最終返回的函數 this 指向不變以及依舊能接受到 e 參數。

立即執行版:

function debounce(func,wait) {let timeout;return function () {let context = this;let args = arguments;if (timeout) clearTimeout(timeout);let callNow = !timeout;timeout = setTimeout(() => {timeout = null;}, wait)if (callNow) func.apply(context, args)} } 復制代碼

立即執行版的意思是觸發事件后函數會立即執行,然后 n 秒內不觸發事件才能繼續執行函數的效果。

使用方法同上,效果如下

在開發過程中,我們需要根據不同的場景來決定我們需要使用哪一個版本的防抖函數,一般來講上述的防抖函數都能滿足大部分的場景需求。但我們也可以將非立即執行版和立即執行版的防抖函數結合起來,實現最終的雙劍合璧版的防抖函數。

雙劍合璧版:

/*** @desc 函數防抖* @param func 函數* @param wait 延遲執行毫秒數* @param immediate true 表立即執行,false 表非立即執行*/ function debounce(func,wait,immediate) {let timeout;return function () {let context = this;let args = arguments;if (timeout) clearTimeout(timeout);if (immediate) {let callNow = !timeout;timeout = setTimeout(() => {timeout = null;}, wait)if (callNow) func.apply(context, args)}else {timeout = setTimeout(() => {func.apply(context, args)}, wait);}} } 復制代碼

節流(throttle)

所謂節流,就是指連續觸發事件但是在 n 秒中只執行一次函數。 節流會稀釋函數的執行頻率。

對于節流,一般有兩種方式可以實現,分別是時間戳版和定時器版。

時間戳版:

function throttle(func, wait) {var previous = 0;return function() {let now = Date.now();let context = this;let args = arguments;if (now - previous > wait) {func.apply(context, args);previous = now;}} } 復制代碼

使用方式如下

content.onmousemove = throttle(count,1000); 復制代碼

效果如下

可以看到,在持續觸發事件的過程中,函數會立即執行,并且每 1s 執行一次。

定時器版:

function throttle(func, wait) {let timeout;return function() {let context = this;let args = arguments;if (!timeout) {timeout = setTimeout(() => {timeout = null;func.apply(context, args)}, wait)}} } 復制代碼

使用方式同上,效果如下

可以看到,在持續觸發事件的過程中,函數不會立即執行,并且每 1s 執行一次,在停止觸發事件后,函數還會再執行一次。

我們應該可以很容易的發現,其實時間戳版和定時器版的節流函數的區別就是,時間戳版的函數觸發是在時間段內開始的時候,而定時器版的函數觸發是在時間段內結束的時候。

同樣地,我們也可以將時間戳版和定時器版的節流函數結合起來,實現雙劍合璧版的節流函數。

雙劍合璧版:

/*** @desc 函數節流* @param func 函數* @param wait 延遲執行毫秒數* @param type 1 表時間戳版,2 表定時器版*/ function throttle(func, wait ,type) {if(type===1){let previous = 0;}else if(type===2){let timeout;}return function() {let context = this;let args = arguments;if(type===1){let now = Date.now();if (now - previous > wait) {func.apply(context, args);previous = now;}}else if(type===2){if (!timeout) {timeout = setTimeout(() => {timeout = null;func.apply(context, args)}, wait)}}} } 復制代碼

覺得還不錯的小伙伴,可以關注一波公眾號哦。

總結

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

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