欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

js防抖-節(jié)流函數(shù)的基本實(shí)現(xiàn)和補(bǔ)充詳解

 更新時(shí)間:2023年01月08日 11:10:31   作者:既白biu  
這篇文章主要介紹了防抖-節(jié)流函數(shù)的基本實(shí)現(xiàn)和補(bǔ)充,文章從基礎(chǔ)概念到手寫(xiě)對(duì)防抖-節(jié)流函數(shù)的實(shí)現(xiàn)進(jìn)行講解,內(nèi)容詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下

前言

防抖和節(jié)流函數(shù)是我們?cè)谄匠i_(kāi)發(fā)的時(shí)候,比較常用的兩個(gè)工具函數(shù),使用防抖和節(jié)流函數(shù)可以提高我們的效率,減小事件觸發(fā)的頻率,可以起到降低服務(wù)器壓力的作用。并且在面試時(shí)候,這兩個(gè)函數(shù)也是會(huì)經(jīng)常會(huì)被問(wèn)到,因此,了解防抖和節(jié)流函數(shù)的基本原理和應(yīng)用場(chǎng)景,并且手寫(xiě)實(shí)現(xiàn)這兩個(gè)函數(shù)至關(guān)重要

防抖函數(shù)

概念和應(yīng)用場(chǎng)景

防抖函數(shù):當(dāng)事件觸發(fā)的時(shí)候,并不會(huì)立刻執(zhí)行,而是會(huì)等待一段事件,當(dāng)事件密集觸發(fā)時(shí)候,函數(shù)的觸發(fā)會(huì)頻繁的被推遲,只有等待了一段時(shí)間也沒(méi)有事件觸發(fā),才會(huì)真正的執(zhí)行。如下圖所示:

防抖的應(yīng)用場(chǎng)景很多:

  • 輸入框中頻繁的輸入內(nèi)容,搜索或者提交信息;
  • 頻繁的點(diǎn)擊按鈕,觸發(fā)某個(gè)事件;
  • 監(jiān)聽(tīng)瀏覽器滾動(dòng)事件,完成某些特定操作;
  • 用戶縮放瀏覽器的resize事件

案例:

在某個(gè)搜索框中輸入自己想要搜索的內(nèi)容:

比如想要搜索一個(gè)MacBook:
當(dāng)我輸入m時(shí),為了更好的用戶體驗(yàn),通常會(huì)出現(xiàn)對(duì)應(yīng)的聯(lián)想內(nèi)容,這些聯(lián)想內(nèi)容通常是保存在服務(wù)器的,所以需要一次網(wǎng)絡(luò)請(qǐng)求;當(dāng)繼續(xù)輸入ma時(shí),再次發(fā)送網(wǎng)絡(luò)請(qǐng)求;
那么macbook一共需要發(fā)送7次網(wǎng)絡(luò)請(qǐng)求; 這大大損耗我們整個(gè)系統(tǒng)的性能,無(wú)論是前端的事件處理,還是對(duì)于服務(wù)器的壓力;

但是我們需要這么多次的網(wǎng)絡(luò)請(qǐng)求嗎?

不需要,正確的做法應(yīng)該是在合適的情況下再發(fā)送網(wǎng)絡(luò)請(qǐng)求; 比如如果用戶快速的輸入一個(gè)macbook,那么只是發(fā)送一次網(wǎng)絡(luò)請(qǐng)求;
比如如果用戶是輸入一個(gè)m想了一會(huì)兒,這個(gè)時(shí)候m確實(shí)應(yīng)該發(fā)送一次網(wǎng)絡(luò)請(qǐng)求;
也就是我們應(yīng)該監(jiān)聽(tīng)用戶在某個(gè)時(shí)間,比如500ms內(nèi),沒(méi)有再次觸發(fā)時(shí)間時(shí),再發(fā)送網(wǎng)絡(luò)請(qǐng)求;
這就是防抖的操作:只有在某個(gè)時(shí)間內(nèi),沒(méi)有再次觸發(fā)某個(gè)函數(shù)時(shí),才真正的調(diào)用這個(gè)函數(shù);

手寫(xiě)實(shí)現(xiàn)防抖函數(shù)

那么如何通過(guò)代碼實(shí)現(xiàn)防抖的功能呢?

首先,防抖函數(shù)應(yīng)該傳入一個(gè)需要實(shí)現(xiàn)防抖的函數(shù),還有一個(gè)時(shí)間,該時(shí)間表示在規(guī)定時(shí)間內(nèi),如果再次觸發(fā)此次事件,則取消上次事件。返回的結(jié)果應(yīng)該是一個(gè)執(zhí)行了此功能的函數(shù)。

那么整體的框架如下,只需要在_debounce函數(shù)里面實(shí)現(xiàn)功能即可。

function debounce(fn,delay){
	const _debounce = function(){
	}
	return _debounce
}

函數(shù)的參數(shù)傳進(jìn)來(lái)一個(gè)時(shí)間,該時(shí)間表示在規(guī)定時(shí)間內(nèi),如果再次觸發(fā)此次事件,則取消上次事件,所以需要有定時(shí)器來(lái)記錄時(shí)間。并且有取消事件的過(guò)程,所以我們需要在滿足條件時(shí)候,取消定時(shí)器,即clearTimeout,那么還有個(gè)問(wèn)題,fn函數(shù)this指向。

如果在_debounce中單獨(dú)調(diào)用傳進(jìn)來(lái)的函數(shù)fn,即以fn()形式直接調(diào)用,那么fn是屬于獨(dú)立的函數(shù)調(diào)用,this指向的是window,實(shí)際this指向的是調(diào)用函數(shù)的對(duì)象,所以會(huì)出現(xiàn)錯(cuò)誤。

我們知道事件調(diào)用的時(shí)候,響應(yīng)函數(shù)參數(shù)會(huì)傳進(jìn)來(lái)一個(gè)event事件對(duì)象,所以我們要對(duì)這個(gè)參數(shù)(event事件對(duì)象)做處理。

那么:

timer定義一個(gè)定時(shí)器,保存上一次的定時(shí)器,在_debounce函數(shù)里面,如果timer不為空,那么先清除上一次的定時(shí)器,之后再給timer賦值,讓他延遲執(zhí)行fn函數(shù),fn函數(shù)用apply改變了this指向,在setTimeout內(nèi)部使用的是箭頭函數(shù),由于箭頭函數(shù)內(nèi)部沒(méi)有this,所以會(huì)去上層找this,那么這個(gè)this實(shí)際上就是調(diào)用debounce的對(duì)象。

比如輸入框的輸入事件做防抖處理:

const inputEl = document.querySelector(“input”)
inputChange是輸入事件觸發(fā)后所要執(zhí)行的函數(shù),可以給他做防抖處理:const debounceChange = debounce(inputChange,3000),然后執(zhí)行: inputEl.oninput = debounceChange,如果不加防抖處理,毫無(wú)疑問(wèn),每次在輸入框輸入時(shí)候,都會(huì)觸發(fā)事件,加了防抖處理后,3秒內(nèi)多次調(diào)用,下一次事件會(huì)把上一次事件清除掉。

這里的this通過(guò)apply調(diào)用后,指向的就是inputEl這個(gè)元素,

function debounce(fn, delay) {
  // 1.定義一個(gè)定時(shí)器, 保存上一次的定時(shí)器
  let timer = null

  // 2.真正執(zhí)行的函數(shù)
  const _debounce = function(...args) {
    // 取消上一次的定時(shí)器
    if (timer) clearTimeout(timer)
    // 延遲執(zhí)行
    timer = setTimeout(() => {
      // 外部傳入的真正要執(zhí)行的函數(shù)
      fn.apply(this, args)
    }, delay)
  }

  return _debounce
}

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

概念和應(yīng)用場(chǎng)景

節(jié)流函數(shù):當(dāng)事件執(zhí)行時(shí)候,會(huì)執(zhí)行這個(gè)事件的響應(yīng)函數(shù);如果這個(gè)事件會(huì)被頻繁觸發(fā),那么節(jié)流函數(shù)會(huì)按照一定的頻率來(lái)執(zhí)行函數(shù);不管在這個(gè)中間有多少次觸發(fā)這個(gè)事件,執(zhí)行函數(shù)的頻繁總是固定的;如圖所示:

節(jié)流的應(yīng)用場(chǎng)景:

  • 監(jiān)聽(tīng)頁(yè)面的滾動(dòng)事件;
  • 鼠標(biāo)移動(dòng)事件;
  • 用戶頻繁點(diǎn)擊按鈕操作;
  • 游戲中的一些設(shè)計(jì)

節(jié)流的具體應(yīng)用場(chǎng)景:
很多人都玩過(guò)類似于飛機(jī)大戰(zhàn)的游戲

在飛機(jī)大戰(zhàn)的游戲中,我們按下空格會(huì)發(fā)射一個(gè)子彈:

很多飛機(jī)大戰(zhàn)的游戲中會(huì)有這樣的設(shè)定,即使按下的頻率非??欤訌椧矔?huì)保持一定的頻率來(lái)發(fā)射;

比如1秒鐘只能發(fā)射一次,即使用戶在這1秒鐘按下了10次,子彈會(huì)保持發(fā)射一顆的頻率來(lái)發(fā)射;

但是事件是觸發(fā)了10次的,響應(yīng)的函數(shù)只觸發(fā)了一次

手寫(xiě)實(shí)現(xiàn)節(jié)流函數(shù)

那么如何通過(guò)代碼實(shí)現(xiàn)防抖的功能呢?

首先,我們需要兩個(gè)變量記錄當(dāng)前事件觸發(fā)的時(shí)間和上一次的開(kāi)始時(shí)間,函數(shù)的參數(shù)會(huì)傳進(jìn)來(lái)間隔的時(shí)間,由此我們可以計(jì)算出下次觸發(fā)的最低間隔時(shí)間,即為間隔時(shí)間-(當(dāng)前事件觸發(fā)的時(shí)間-上次的開(kāi)始時(shí)間),如果間隔時(shí)間<=0,那么執(zhí)行fn函數(shù),并且修改上一次的開(kāi)始時(shí)間為當(dāng)前事件觸發(fā)時(shí)間。

function throttle(fn, interval) {
  // 1.記錄上一次的開(kāi)始時(shí)間
  let lastTime = 0

  // 2.事件觸發(fā)時(shí), 真正執(zhí)行的函數(shù)
  const _throttle = function(...args) {

    // 2.1.獲取當(dāng)前事件觸發(fā)時(shí)的時(shí)間
    const nowTime = new Date().getTime()

    // 2.2.使用當(dāng)前觸發(fā)的時(shí)間和之前的時(shí)間間隔以及上一次開(kāi)始的時(shí)間, 計(jì)算出還剩余多長(zhǎng)事件需要去觸發(fā)函數(shù)
    const remainTime = interval - (nowTime - lastTime)
    if (remainTime <= 0) {
      // 2.3.真正觸發(fā)函數(shù)
      fn.apply(this,args)
      // 2.4.保留上次觸發(fā)的時(shí)間
      lastTime = nowTime
    }
  }

  return _throttle
}

到此這篇關(guān)于js防抖-節(jié)流函數(shù)的基本實(shí)現(xiàn)和補(bǔ)充詳解的文章就介紹到這了,更多相關(guān)js防抖節(jié)流函數(shù)的實(shí)現(xiàn)內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • 微信小程序常用簡(jiǎn)易小函數(shù)總結(jié)

    微信小程序常用簡(jiǎn)易小函數(shù)總結(jié)

    這篇文章主要介紹了微信小程序常用簡(jiǎn)易小函數(shù),結(jié)合實(shí)例形式總結(jié)分析了微信小程序提示、登陸、驗(yàn)證、session操作等相關(guān)操作函數(shù)與使用技巧,需要的朋友可以參考下
    2019-02-02
  • JS中去掉if...else的多種方法

    JS中去掉if...else的多種方法

    在JavaScript編程中,過(guò)多的if...elseif...else語(yǔ)句可能導(dǎo)致代碼難以維護(hù),可以通過(guò)switch語(yǔ)句、對(duì)象字面量、函數(shù)映射、數(shù)組或映射對(duì)象分發(fā)、提前返回以及使用數(shù)組的find方法來(lái)優(yōu)化這種復(fù)雜的條件判斷,提高代碼的可讀性和維護(hù)性,下面就來(lái)介紹一下
    2024-09-09
  • 多個(gè)上傳文件用js驗(yàn)證文件的格式和大小的方法(推薦)

    多個(gè)上傳文件用js驗(yàn)證文件的格式和大小的方法(推薦)

    下面小編就為大家?guī)?lái)一篇多個(gè)上傳文件用js驗(yàn)證文件的格式和大小的方法(推薦)。小編覺(jué)得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧
    2017-03-03
  • JavaScript中字符串GBK與GB2312的編解碼示例講解

    JavaScript中字符串GBK與GB2312的編解碼示例講解

    在瀏覽器JavaScript環(huán)境中,可以使用TextEncoder和TextDecoder?API?來(lái)進(jìn)行?GBK?編碼和解碼,也可以使用?encodeURIComponent?函數(shù)對(duì)字符串進(jìn)行編碼,最好使用第三方庫(kù),比如iconv-lite來(lái)實(shí)現(xiàn)
    2023-12-12
  • 詳解JVM系列之內(nèi)存模型

    詳解JVM系列之內(nèi)存模型

    JVM是一種用于計(jì)算設(shè)備的規(guī)范,它是一個(gè)虛構(gòu)出來(lái)的機(jī)器,是通過(guò)在實(shí)際的計(jì)算機(jī)上仿真模擬各種功能實(shí)現(xiàn)的。JVM的內(nèi)存區(qū)域可以被分為:線程、棧、堆、靜態(tài)方法區(qū)。本文將介紹JVM的內(nèi)存模型,感興趣的小伙伴,可以參考下
    2021-06-06
  • JavaScript中this的四個(gè)綁定規(guī)則總結(jié)

    JavaScript中this的四個(gè)綁定規(guī)則總結(jié)

    相信大家都知道,ES5及之前時(shí)代的JavaScript中this的綁定機(jī)制是讓很多開(kāi)發(fā)者頭疼不已的事情。this 的綁定變化多端,讓筆者也吃了不少虧。所以本文總結(jié)了this的四條綁定規(guī)則,在此記錄,以防自己遺忘,也方便他人參考借鑒。下面來(lái)一起看看吧。
    2016-09-09
  • Javascript 詳解封裝from表單數(shù)據(jù)為json串進(jìn)行ajax提交

    Javascript 詳解封裝from表單數(shù)據(jù)為json串進(jìn)行ajax提交

    這篇文章主要介紹了Javascript 詳解封裝from表單數(shù)據(jù)為json串進(jìn)行ajax提交的相關(guān)資料,需要的朋友可以參考下
    2017-03-03
  • JS實(shí)現(xiàn)添加,替換,刪除節(jié)點(diǎn)元素的方法

    JS實(shí)現(xiàn)添加,替換,刪除節(jié)點(diǎn)元素的方法

    這篇文章主要介紹了JS實(shí)現(xiàn)添加,替換,刪除節(jié)點(diǎn)元素的方法,實(shí)例分析了javascript針對(duì)節(jié)點(diǎn)元素的替換、刪除及常用的幾種添加技巧,需要的朋友可以參考下
    2016-06-06
  • js二維數(shù)組定義和初始化的三種方法總結(jié)

    js二維數(shù)組定義和初始化的三種方法總結(jié)

    本篇文章主要是對(duì)js二維數(shù)組定義和初始化的三種方法進(jìn)行了總結(jié)介紹,需要的朋友可以過(guò)來(lái)參考下,希望對(duì)大家有所幫助
    2014-03-03
  • 最新熱門腳本Autojs源碼分享

    最新熱門腳本Autojs源碼分享

    AutoJS 是基于一個(gè)標(biāo)準(zhǔn)字典庫(kù)的文本輸入自動(dòng)完成 JavaScript 庫(kù)。Auto.js 是使用純 JS 實(shí)現(xiàn)的,沒(méi)有任務(wù)外部依賴,大小僅僅 6kb,本文給大家分享最新熱門腳本Autojs源碼,感興趣的朋友一起看看吧
    2021-05-05

最新評(píng)論