最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

一文教你徹底學(xué)會(huì)JavaScript手寫防抖節(jié)流

 更新時(shí)間:2022年11月30日 10:04:37   作者:快跑啊小盧_  
其實(shí)防抖和節(jié)流不僅僅在面試中會(huì)讓大家手寫,在實(shí)際項(xiàng)目中也可以起到性能優(yōu)化的作用,所以還是很有必要掌握的。本文就帶大家徹底學(xué)會(huì)JavaScript手寫防抖節(jié)流,需要的可以參考一下

前言

  • 前段時(shí)間群友說(shuō)面試的時(shí)候老是分不清防抖和節(jié)流。
  • 其實(shí)防抖和節(jié)流不僅僅在面試中會(huì)讓大家手寫,在實(shí)際項(xiàng)目中也可以起到性能優(yōu)化的作用,所以還是很有必要掌握的。
  • 接下來(lái)我就用一杯茶的時(shí)間帶大家徹底學(xué)會(huì)手寫防抖和節(jié)流。

防抖

個(gè)例子

我們先拋開(kāi)概念不談,其實(shí)在生活中也有很多防抖的例子:

  • 比如你現(xiàn)在使用的電腦,在不使用后一段時(shí)間自動(dòng)休眠
  • 當(dāng)你再次使用的時(shí)候重新激活,并開(kāi)始你設(shè)置的時(shí)間倒計(jì)時(shí)10分鐘
  • 在這10分鐘內(nèi)你繼續(xù)使用電腦又會(huì)重新開(kāi)始倒計(jì)時(shí)10分鐘
  • 當(dāng)你最后一次使用電腦并離開(kāi)時(shí)重新倒計(jì)時(shí)10分鐘過(guò)去了,電腦就休眠了

這其實(shí)這就是防抖的基本概念了~說(shuō)白了就是在一段時(shí)間只執(zhí)行一次,也就是我們上面的電腦只打開(kāi)這一次。

我們上面的使用電腦可以理解為觸發(fā)事件,而與我上面標(biāo)注的setTimeoutclearTimeout其實(shí)就是防抖的主要要素了。

當(dāng)然上面的是生活中的例子,那我們?cè)谖覀兊娜粘i_(kāi)發(fā)中其實(shí)也經(jīng)常用到,比如我們調(diào)整頁(yè)面的大小,驗(yàn)證表單某個(gè)字段是否重復(fù)時(shí)發(fā)生請(qǐng)求次數(shù)控制,防止表單多次提交等。

手寫防抖

說(shuō)了這么多,相信大家大概理解了防抖的概念,那我們現(xiàn)在來(lái)實(shí)現(xiàn)一個(gè)防抖吧,假設(shè)我們要點(diǎn)擊一個(gè)按鈕新增一條信息,當(dāng)然我們不希望每次點(diǎn)擊都調(diào)用接口新增,我們希望多次點(diǎn)擊只新增一次,這時(shí)候我們?cè)撛趺磳懩兀?/p>

首先我們先簡(jiǎn)單的模擬一個(gè)按鈕被點(diǎn)擊的過(guò)程。

// debounce.js
let addBtn=document.getElementById('add')
function addOne(){
  console.log('增加一個(gè)')
}
addBtn.addEventListener('click',addOne)

因?yàn)槲覀冃枰獙?duì)執(zhí)行的事件進(jìn)行處理所以接下來(lái)我們需要封裝一下addOne函數(shù)。

// debounce.js
let addBtn=document.getElementById('add')
function addOne(){
  console.log('增加一個(gè)')
}
function debounce(fun){
  return function(){
    fun()
  }
}
addBtn.addEventListener('click',debounce(addOne))

上面我們用閉包處理了一下addOne函數(shù),接下來(lái)我們需要添加一個(gè)延時(shí)器setTimeout來(lái)倒計(jì)時(shí),當(dāng)我們點(diǎn)擊按鈕后過(guò)2s再執(zhí)行。

// debounce.js
function debounce(fun,time){
  return function(){
    setTimeout(()=>{
      fun()
    },time)
  }
}
addBtn.addEventListener('click',debounce(addOne,2000))

現(xiàn)在延時(shí)的目的是達(dá)到了但是每次點(diǎn)擊都會(huì)新增一個(gè)新的setTimeout而且并不能達(dá)到我們多次點(diǎn)擊只執(zhí)行一次的效果。

這時(shí)候就需要clearTimeout登場(chǎng)了,我們需要在我們點(diǎn)擊了按鈕后也就是debounce執(zhí)行時(shí)要先把之前的setTimeout先清除再重新計(jì)時(shí)。

function debounce(fun,time){
  let timer
  return function(){
    clearTimeout(timer)
    timer=setTimeout(()=>{
      fun()
    },time)
  }
}

現(xiàn)在我們的一個(gè)防抖功能就完成了,但是這還沒(méi)完,如果我們?cè)?code>addOne()打印this會(huì)發(fā)現(xiàn)我們這樣執(zhí)行的this是指向Window的。

這當(dāng)然不是我們所希望的,我們需要使用apply來(lái)改變this指向,再者就是我們需要考慮到執(zhí)行函數(shù)的參數(shù),因?yàn)椴煌暮瘮?shù)肯定會(huì)有不同的參數(shù)傳入,對(duì)于參數(shù)我們可以使用arguments處理。

function debounce(fun,time){
  let timer
  return function(){
    clearTimeout(timer)
    let args = arguments
    timer=setTimeout(()=>{
      fun.apply(this,args)
    },time)
  }
}

這樣我們的防抖函數(shù)就手寫完成了,看起來(lái)其實(shí)也并不難。

總而言之防抖就是在不斷的操作中(輸入、點(diǎn)擊等)最終只執(zhí)行一次的一種提高性能的方法。

節(jié)流

舉個(gè)例子

當(dāng)然我們生活中也會(huì)有很多節(jié)流的的例子,不知道大家有沒(méi)有留意過(guò)公園的灑水機(jī):

  • 一般我們會(huì)給灑水機(jī)設(shè)定一個(gè)時(shí)間假設(shè)30min
  • 當(dāng)距離上次灑水時(shí)間未夠30min的時(shí)候一直保持靜止?fàn)顟B(tài)
  • 而當(dāng)?shù)搅?code>30min則會(huì)觸發(fā)灑水的事件

  • 這其實(shí)也是節(jié)流的最基本的概念了,說(shuō)白了就是在間隔一段時(shí)間執(zhí)行一次
  • 我們上面的灑水可以理解為觸發(fā)事件,而我們上面標(biāo)注的其他信息也就只有30min和當(dāng)前時(shí)間,這兩個(gè)就是節(jié)流的主要要素了。
  • 當(dāng)然上面的是我們的生活中的例子,那我們?cè)谖覀兊娜粘i_(kāi)發(fā)中其實(shí)也經(jīng)常用到,比如我們滾動(dòng)鼠標(biāo)滾輪監(jiān)聽(tīng)滾動(dòng)條位置,防止按鈕多次點(diǎn)擊等。

手寫節(jié)流

說(shuō)了這么多,相信大家大概理解了節(jié)流的概念,那我們現(xiàn)在來(lái)實(shí)現(xiàn)一個(gè)節(jié)流吧,假設(shè)我們現(xiàn)在要實(shí)現(xiàn)一個(gè)鼠標(biāo)滾動(dòng)打印事件,想讓它在3s執(zhí)行一次,這時(shí)候我們?cè)撛趺磳懩兀?/p>

首先我們先模擬一個(gè)觸發(fā)事件。

// throttle.js
function scrollTest(){
  console.log('現(xiàn)在我觸發(fā)了')
}
document.addEventListener('scroll',scrollTest)

接下來(lái)我們封裝一個(gè)節(jié)流函數(shù),跟防抖一樣我們也需要利用閉包,順便再加一個(gè)參數(shù)接收節(jié)流時(shí)間。

// throttle.js
...
function throttle(fun,time){
  return function(){
    fun()
  }
}
document.addEventListener('scroll',throttle(scrollTest,3000))

因?yàn)槲覀兊墓?jié)流是在一段時(shí)間內(nèi)執(zhí)行一次也就是說(shuō)如果兩次鼠標(biāo)滾動(dòng)的時(shí)間間隔未到所設(shè)置的時(shí)間則不執(zhí)行

那我們可以記錄一下每次滾動(dòng)的時(shí)間戳來(lái)進(jìn)行對(duì)比。

// throttle.js
...
function throttle(fun,time){
  let t1=0 //初始時(shí)間
  return function(){
    let t2=new Date() //當(dāng)前時(shí)間
    if(t2-t1>time){
      fun()
      t1=t2
    }
  }
}

我們會(huì)記錄兩個(gè)時(shí)間一個(gè)是t1代表初始時(shí)間一個(gè)是t2代表當(dāng)前時(shí)間,如果當(dāng)前時(shí)間距離上一個(gè)時(shí)間也就是初始時(shí)間大于所設(shè)置的time

那我們就可以執(zhí)行fun()并且把初始時(shí)間變更為這一次執(zhí)行的時(shí)間,這樣每次我們執(zhí)行過(guò)后t1就變成了上一次執(zhí)行的時(shí)間。

這樣我們的一個(gè)節(jié)流功能就完成了。

// throttle.js
...
function throttle(fun,time){
  let t1=0 //初始時(shí)間
  return function(){
    let t2=new Date() //當(dāng)前時(shí)間
    if(t2-t1>time){
      fun()
      t1=t2
    }
  }
}

當(dāng)然我們也需要像防抖一樣改變this指向和接收參數(shù),最后完成后是這樣的。

// throttle.js
...
function throttle(fun,time){
  let t1=0 //初始時(shí)間
  return function(){
    let t2=new Date() //當(dāng)前時(shí)間
    if(t2-t1>time){
      fun.apply(this,arguments)
      t1=t2
    }
  }
}

至此一個(gè)節(jié)流函數(shù)就手寫完成了,是不是也不會(huì)很難呢?

總而言之節(jié)流就是在一段時(shí)間內(nèi)不斷操作而在你規(guī)定的時(shí)間內(nèi)只執(zhí)行一次的一種提高性能的方法

寫在最后

  • 首先還是很感謝大家看到這里,這次的文章就分享到這里~
  • 對(duì)于防抖和節(jié)流一個(gè)最主觀的判斷方法就是:在10s內(nèi)你瘋狂點(diǎn)擊一個(gè)按鈕,如果使用了防抖則會(huì)只執(zhí)行一次,而你使用了節(jié)流則會(huì)每隔一段時(shí)間執(zhí)行一次,這個(gè)時(shí)間可以自己來(lái)掌控。
  • 當(dāng)然防抖和節(jié)流的變形還是有很多的,根據(jù)不同的需求來(lái)變換不同的函數(shù)但是萬(wàn)變不離其宗,只要你搞懂了上面的方法,其他的就沒(méi)有問(wèn)題了。

以上就是一文教你徹底學(xué)會(huì)JavaScript手寫防抖節(jié)流的詳細(xì)內(nèi)容,更多關(guān)于JavaScript防抖節(jié)流的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • JavaScript腳本實(shí)現(xiàn)解析MyBatis?SQL日志

    JavaScript腳本實(shí)現(xiàn)解析MyBatis?SQL日志

    這篇文章主要為大家詳細(xì)介紹了如何開(kāi)發(fā)一個(gè)簡(jiǎn)單的?HTML?和?JavaScript?腳本,用于解析?MyBatis?的?SQL?日志并生成可執(zhí)行的?SQL?語(yǔ)句,需要的可以參考下
    2025-02-02
  • 拖動(dòng)時(shí)防止選中

    拖動(dòng)時(shí)防止選中

    本文主要介紹了拖動(dòng)時(shí)防止選中的小知識(shí)點(diǎn)。具有很好的參考價(jià)值,下面跟著小編一起來(lái)看下吧
    2017-02-02
  • JavaScript?微任務(wù)和宏任務(wù)講解

    JavaScript?微任務(wù)和宏任務(wù)講解

    這篇文章主要分享了JavaScript?微任務(wù)和宏任務(wù)講解,在js中,我們一般將所有的任務(wù)都分成兩類,一種是同步任務(wù),另外一種是異步任務(wù)。而在異步任務(wù)中,又有著更加細(xì)致的分類,那就是微任務(wù)和宏任務(wù),下面來(lái)一起學(xué)習(xí)js中的微任務(wù)和宏任務(wù)吧
    2021-12-12
  • 教你使用webpack打包編譯TypeScript代碼

    教你使用webpack打包編譯TypeScript代碼

    TypeScript同樣也可以結(jié)合構(gòu)建工具一起使用,下邊以webpack為例介紹一下如何結(jié)合構(gòu)建工具使用TypeScript,本文分步驟給大家介紹的非常詳細(xì),需要的朋友參考下吧
    2021-06-06
  • 京東優(yōu)選小程序的實(shí)現(xiàn)代碼示例

    京東優(yōu)選小程序的實(shí)現(xiàn)代碼示例

    這篇文章主要介紹了京東優(yōu)選小程序的實(shí)現(xiàn)代碼示例,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2020-02-02
  • 詳解JavaScript中ora庫(kù)的使用教程

    詳解JavaScript中ora庫(kù)的使用教程

    使用 ora 這個(gè) JavaScript 庫(kù)可以在命令行應(yīng)用程序中提供漂亮的加載狀態(tài)提示,本文詳細(xì)介紹如何使用該庫(kù),希望對(duì)大家有一定的幫助
    2024-02-02
  • 如何利用JS實(shí)現(xiàn)時(shí)間軸動(dòng)畫效果

    如何利用JS實(shí)現(xiàn)時(shí)間軸動(dòng)畫效果

    時(shí)間軸動(dòng)畫和幀式動(dòng)畫有很大不同,但相比之下時(shí)間軸方式來(lái)的更直觀和簡(jiǎn)便,下面這篇文章主要給大家介紹了關(guān)于如何利用JS實(shí)現(xiàn)時(shí)間軸動(dòng)畫效果的相關(guān)資料,文中通過(guò)實(shí)例代碼介紹的非常詳細(xì),需要的朋友可以參考下
    2022-06-06
  • canvas繪制一個(gè)常用的emoji表情

    canvas繪制一個(gè)常用的emoji表情

    本文主要介紹了canvas繪制一個(gè)常用的emoji表情的示例代碼。具有很好的參考價(jià)值,下面跟著小編一起來(lái)看下吧
    2017-03-03
  • ES6知識(shí)點(diǎn)整理之對(duì)象解構(gòu)賦值應(yīng)用示例

    ES6知識(shí)點(diǎn)整理之對(duì)象解構(gòu)賦值應(yīng)用示例

    這篇文章主要介紹了ES6知識(shí)點(diǎn)整理之對(duì)象解構(gòu)賦值應(yīng)用,結(jié)合實(shí)例形式分析了ES6對(duì)象解構(gòu)賦值相關(guān)概念、原理、出現(xiàn)的問(wèn)題及相應(yīng)解決方法,需要的朋友可以參考下
    2019-04-04
  • JavaScript加強(qiáng)之自定義event事件

    JavaScript加強(qiáng)之自定義event事件

    event事件在本文以自定義的方式出現(xiàn),感興趣的朋友可以參考下,希望對(duì)大家有所幫助
    2013-09-09

最新評(píng)論

报价| 安溪县| 霍山县| 于都县| 筠连县| 乌拉特后旗| 南投市| 鄂伦春自治旗| 莎车县| 华安县| 鄂州市| 县级市| 五峰| 乌兰浩特市| 南平市| 宁阳县| 南阳市| 铜鼓县| 凤阳县| 射阳县| 深州市| 镇坪县| 云和县| 偏关县| 隆子县| 清新县| 象山县| 保定市| 福泉市| 栾川县| 泽州县| 彭山县| 姜堰市| 高雄市| 宜春市| 泸水县| 绥宁县| 石家庄市| 赫章县| 永济市| 恩施市|