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

JS防抖節(jié)流函數(shù)的實(shí)現(xiàn)與使用場(chǎng)景

 更新時(shí)間:2021年07月13日 11:40:56   作者:一只小web  
在行走江湖的過(guò)程中,會(huì)出現(xiàn)很多性能優(yōu)化的問(wèn)題來(lái)讓你手足無(wú)措,那么這篇文章主要給大家介紹了關(guān)于JS防抖節(jié)流函數(shù)的實(shí)現(xiàn)與使用場(chǎng)景,針對(duì)這兩個(gè)問(wèn)題來(lái)為你答疑解惑,需要的朋友可以參考下

一、什么是函數(shù)防抖

概念:函數(shù)防抖(debounce),就是指觸發(fā)事件后,在 n 秒內(nèi)函數(shù)只能執(zhí)行一次,如果觸發(fā)事件后在 n 秒內(nèi)又觸發(fā)了事件,則會(huì)重新計(jì)算函數(shù)延執(zhí)行時(shí)間。

1、為什么需要函數(shù)防抖?

前端開(kāi)發(fā)過(guò)程中,有一些事件,常見(jiàn)的例如,onresize,scroll,mousemove ,mousehover 等,會(huì)被頻繁觸發(fā)(短時(shí)間內(nèi)多次觸發(fā)),不做限制的話,有可能一秒之內(nèi)執(zhí)行幾十次、幾百次,如果在這些函數(shù)內(nèi)部執(zhí)行了其他函數(shù),尤其是執(zhí)行了操作 DOM 的函數(shù)(瀏覽器操作 DOM 是很耗費(fèi)性能的),那不僅會(huì)浪費(fèi)計(jì)算機(jī)資源,還會(huì)降低程序運(yùn)行速度,甚至造成瀏覽器卡死、崩潰。

2、函數(shù)防抖的要點(diǎn)

函數(shù)防抖的要點(diǎn),是需要一個(gè) setTimeout 來(lái)輔助實(shí)現(xiàn),延遲運(yùn)行需要執(zhí)行的代碼。如果方法多次觸發(fā),則把上次記錄的延遲執(zhí)行代碼用 clearTimeout 清掉,重新開(kāi)始計(jì)時(shí)。若計(jì)時(shí)期間事件沒(méi)有被重新觸發(fā),等延遲時(shí)間計(jì)時(shí)完畢,則執(zhí)行目標(biāo)代碼。

3、函數(shù)防抖的實(shí)現(xiàn)

//HTML部分
 <div>
    賬戶:<input type="text" id="myinput">
</div>
//JS部分
function debounce(fun,wait=1500){//ES6語(yǔ)法 wait=1500 設(shè)置參數(shù)默認(rèn)值,如果沒(méi)有輸入wait就會(huì)使用1500
        let timeout = null
        return function(){
            if(timeout){//如果存在定時(shí)器就清空
                clearTimeout(timeout)
            }
            timeout=setTimeout(function(){
                fun()
            },wait)
        }

    }
function testUname(){
    console.log("輸入結(jié)束!")
}
document.getElementById('myinput').addEventListener('input',debounce(testUname,1000))

上面的代碼就是防抖函數(shù)的簡(jiǎn)單運(yùn)用,只要你每次輸入間隔大于一秒,那么永遠(yuǎn)不會(huì)打“印輸入結(jié)束!”,直到你停止輸入嗎,這是因?yàn)槊恳淮蔚妮斎攵紩?huì)清除上一次的計(jì)時(shí)器。

看到這里你以為就結(jié)束了嗎?別急,讓我們繼續(xù)看:

//HTML部分
 <div>
    賬戶:<input type="text" id="myinput">
</div>
//JS部分
function debounce(fun,wait=1500){
        let timeout = null
        return function(){
            console.log(this)//<input id="myinput" type="text">
            console.log(arguments)//Arguments { 0: input, … }
            if(timeout){//如果存在定時(shí)器就清空
                clearTimeout(timeout)
            }
            timeout=setTimeout(function(){
                console.log(this)//Window
                console.log(arguments)//Arguments { … }
                fun()
            },wait)
        }

    }
function testUname(){
    console.log("輸入結(jié)束!")
}
document.getElementById('myinput').addEventListener('input',debounce(testUname,1000))

無(wú)論是防抖還是節(jié)流,我們都要解決兩個(gè)問(wèn)題,this指向和arguments。

如果沒(méi)有特殊指向,setInterval和setTimeout的回調(diào)函數(shù)中this的指向都是window。這是因?yàn)镴S的定時(shí)器方法是定義在window下的。這顯然不是我們希望的,因?yàn)槲覀儽O(jiān)聽(tīng)的是input輸入框,所以我們希望定時(shí)器里面的this指向input。

那么有什么方法可以改變this指向嗎?

一種簡(jiǎn)單的辦法就是我們可以用參數(shù)把定時(shí)器外層函數(shù)的this和arguments保存下來(lái)。然后再通過(guò)apply改變定時(shí)器要執(zhí)行的函數(shù)fun的指向。

//JS部分
function debounce(fun,wait=1500){
            let timeout = null
            return function(){
                let _this = this
                let arg = arguments
                if(timeout){//如果存在定時(shí)器就清空
                    clearTimeout(timeout)
                }
                timeout=setTimeout(function(){
                    console.log(_this)//<input id="myinput" type="text">
                    console.log(arg)//Arguments { 0: input, … }
                    fun.apply(_this,arg)
                },wait)
            }
         
        }

當(dāng)然,你也可以用ES6的箭頭函數(shù)新特性:箭頭函數(shù)的 this 始終指向函數(shù)定義時(shí)的 this,而非執(zhí)行時(shí)。箭頭函數(shù)需要記著這句話:“箭頭函數(shù)中沒(méi)有 this 綁定,必須通過(guò)查找作用域鏈來(lái)決定其值,如果箭頭函數(shù)被非箭頭函數(shù)包含,則 this 綁定的是最近一層非箭頭函數(shù)的 this,否則,this 為 undefined”。

所以也可以這樣寫:

//JS部分
function debounce(fun,wait=1500){
            let timeout = null
            return function(){
                if(timeout){//如果存在定時(shí)器就清空
                    clearTimeout(timeout)
                }
                timeout=setTimeout(()=>{
                    console.log(this)//<input id="myinput" type="text">
                    console.log(arguments)//Arguments { 0: input, … }
                    fun.apply(this,arguments)
                },wait)
            }
         
        }

4、函數(shù)防抖的使用場(chǎng)景

函數(shù)防抖一般用在什么情況之下呢?一般用在,連續(xù)的事件只需觸發(fā)一次回調(diào)的場(chǎng)合。具體有:

  • 搜索框搜索輸入。只需用戶最后一次輸入完,再發(fā)送請(qǐng)求;
  • 用戶名、手機(jī)號(hào)、郵箱輸入驗(yàn)證;
  • 瀏覽器窗口大小改變后,只需窗口調(diào)整完后,再執(zhí)行 resize 事件中的代碼,防止重復(fù)渲染。

二、什么是函數(shù)節(jié)流

概念: 限制一個(gè)函數(shù)在一定時(shí)間內(nèi)只能執(zhí)行一次。

舉個(gè)栗子,坐火車或地鐵,過(guò)安檢的時(shí)候,在一定時(shí)間(例如10秒)內(nèi),只允許一個(gè)乘客通過(guò)安檢入口,以配合安檢人員完成安檢工作。上例中,每10秒內(nèi),僅允許一位乘客通過(guò),分析可知,“函數(shù)節(jié)流”的要點(diǎn)在于,在 一定時(shí)間 之內(nèi),限制 一個(gè)動(dòng)作 只 執(zhí)行一次 。

1、函數(shù)節(jié)流的要點(diǎn)

主要實(shí)現(xiàn)思路就是通過(guò) setTimeout 定時(shí)器,通過(guò)設(shè)置延時(shí)時(shí)間,在第一次調(diào)用時(shí),創(chuàng)建定時(shí)器,先設(shè)定一個(gè)變量,然后把定時(shí)器賦值給這個(gè)變量,再寫入需要執(zhí)行的函數(shù)。第二次執(zhí)行這個(gè)函數(shù)時(shí),會(huì)判斷變量是否true,是則返回。當(dāng)?shù)谝淮蔚亩〞r(shí)器執(zhí)行完函數(shù)最后會(huì)設(shè)定變量為false。那么下次判斷變量時(shí)則為false,函數(shù)會(huì)依次運(yùn)行。目的在于在一定的時(shí)間內(nèi),保證多次函數(shù)的請(qǐng)求只執(zhí)行最后一次調(diào)用。
這么看是不是有點(diǎn)看不懂?讓我們來(lái)看代碼:

2、函數(shù)節(jié)流的實(shí)現(xiàn)

//JS部分
function debounce(fun,wait=1000){//定時(shí)器方案
            let timer = null;//先設(shè)定一個(gè)變量
            return function(){
                if(!timer){//如果timer為null就進(jìn)入
                    timer = setTimeout(function(){//然后把定時(shí)器賦值給這個(gè)變量
                        fun()//再寫入需要執(zhí)行的函數(shù)
                        timer = null//第一次的定時(shí)器執(zhí)行完函數(shù)最后會(huì)設(shè)定變量為false,這里的 timer = null有兩個(gè)作用,1、開(kāi)啟下一次的入口,2、清除后面的定時(shí)器
                    })

                }
            }
        }
function testUname(){
    console.log(Math.random())
}
document.getElementById('myinput').addEventListener('input',debounce(testUname))

同樣的,節(jié)流函數(shù)也要解決this和arguments的問(wèn)題,改進(jìn)后如下:

//箭頭函數(shù)寫法
function debounce(fun,wait=1000){
            let timer = null
            return function(){
                if(!timer){
                    timer = setTimeout(()=>{
                        fun.apply(this,arguments)
                        timer = null
                    },wait)

                }
            }
}
//參數(shù)保存法
function debounce(fun,wait=1000){
        let timer = null
        return function(){
            let _this = this
            let arg = arguments
            if(!timer){
                timer = setTimeout(function(){
                    fun.apply(_this,arg)
                    timer = null
                },wait)

            }
        }
}

3、函數(shù)節(jié)流的使用場(chǎng)景

到此為止,相信各位應(yīng)該對(duì)函數(shù)節(jié)流有了一個(gè)比較詳細(xì)的了解,那函數(shù)節(jié)流一般用在什么情況之下呢?

  • 懶加載、滾動(dòng)加載、加載更多或監(jiān)聽(tīng)滾動(dòng)條位置;
  • 百度搜索框,搜索聯(lián)想功能;
  • 防止高頻點(diǎn)擊提交,防止表單重復(fù)提交;

總結(jié)

到此這篇關(guān)于JS防抖節(jié)流函數(shù)的實(shí)現(xiàn)與使用場(chǎng)景的文章就介紹到這了,更多相關(guān)JS防抖節(jié)流函數(shù)內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

最新評(píng)論