適合小白看的前端防抖節(jié)流

防抖 操作時(shí)不執(zhí)行 確定不操作了才執(zhí)行莫换,在前端應(yīng)用場(chǎng)景還是比較多的

好比你在一直玩手機(jī)的時(shí)候,手機(jī)不會(huì)息屏 玩了一分鐘不玩了 就息屏了

原理: 操作(你快動(dòng)我爸枇濉)=>關(guān)閉定時(shí)器(好了拉岁,我要重新數(shù)數(shù)了)=>重新開始計(jì)算器(你再不動(dòng)我就要息屏了)=>執(zhí)行(手機(jī)息屏了)

如何去實(shí)現(xiàn)這么一個(gè)函數(shù)

1.創(chuàng)建一個(gè)函數(shù),他接受倆個(gè)參數(shù)惰爬,一個(gè)是你想去防抖的函數(shù)喊暖,一個(gè)是你想延時(shí)操作的時(shí)間

function debounce(fun,delay){

}

2.他返回一個(gè)自執(zhí)行函數(shù),并且這個(gè)函數(shù)在 delay后執(zhí)行

function debounce(fun,delay){
    return function(){
        setTimeout(()=>{
            fun()
        },delay)
    }
}

此時(shí)其實(shí)已經(jīng)實(shí)現(xiàn)了一個(gè)延時(shí)函數(shù)了撕瞧,但是需要自執(zhí)行一下陵叽,因?yàn)槲覀兎祷氐氖呛瘮?shù)體狞尔,可以使用debounce(fun,delay)(),或者return function(){}()加個(gè)括弧

function debounce(fun,delay){
    return function(){
        setTimeout(()=>{
            fun()
        },delay)
    }
}

function sleep(){
    console.log(1)
}
debounce(sleep,3000)()

那當(dāng)然這種代碼肯定沒有如下來的簡(jiǎn)潔

const sleep = time =>{
  return new Promise(resolve=>setTimeout(resolve,time))
}

3.再來看一遍原理 操作=>關(guān)閉定時(shí)器=>重新開始計(jì)算器=>執(zhí)行,那么接下來就是對(duì)定時(shí)器的操作巩掺,我們聲明一個(gè)定時(shí)器然后并覆蓋

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

那么到這步沪么,其實(shí)已經(jīng)實(shí)現(xiàn)了大多數(shù)的防抖,我們嘗試一下

function watchResize() {
    console.log(1)
}
window.addEventListener('resize', debounces(watchResize, 1000))

在頁(yè)面中進(jìn)行窗口改變的時(shí)候锌半,當(dāng)你停止改變1s后就會(huì)打印1禽车,當(dāng)然這個(gè)函數(shù)還有一些優(yōu)化,比如對(duì)fn的類型判斷刊殉,delay的處理等等殉摔,了解基礎(chǔ)原理之后 稍微進(jìn)階一下

<input type="text" id="ipt">

比如我們寫個(gè)input,給它綁定一個(gè)input事件

ipt.oninput = function(){
    console.log(this.value)
}

OK记焊,此時(shí)沒有問題逸月,但是我們想要用戶最后輸入的值,做個(gè)防抖

ipt.oninput = debounce(function () { 
    console.log(this.value)
 }, 2000)

此時(shí)控制臺(tái)你會(huì)發(fā)現(xiàn)遍膜,打印的是undefined碗硬,問題就出在this指向問題

ES5: 一個(gè)函數(shù)在被調(diào)用時(shí),會(huì)自動(dòng)取得兩個(gè)特殊變量:this和arguments瓢颅。在全局環(huán)境調(diào)用函數(shù)時(shí)恩尾,this代表window對(duì)象;而當(dāng)函數(shù)被作為其他某個(gè)對(duì)象的方法而調(diào)用時(shí)挽懦,this就代表那個(gè)對(duì)象翰意。

簡(jiǎn)而言之: ES5的函數(shù)中,this是執(zhí)行時(shí)函數(shù)所在的那個(gè)對(duì)象信柿。

function debounce(fun, delay) {
    console.log(this)  //此處打印的是windows
    let timer
    return function () {
        //此處是執(zhí)行環(huán)境  因?yàn)榉祷氐暮瘮?shù) 在xx環(huán)境下觸發(fā)的  xx就是調(diào)用的對(duì)象
        console.log(this)
        if (timer) clearTimeout(timer)
        timer = setTimeout(() => {
            fun()
        }, delay)
    }
}

所以我們?cè)诙〞r(shí)器的函數(shù)執(zhí)行顯示綁定當(dāng)前的this即可

function debounce(fun, delay) {
    let timer
    return function () {
        if (timer) clearTimeout(timer)
        timer = setTimeout(() => {
            fun.apply(this)
        }, delay)
    }
}

同理冀偶,調(diào)用的時(shí)候就不能使用箭頭函數(shù),箭頭函數(shù)不存在this渔嚷,當(dāng)然你非要用 进鸠,可以這樣用

const co = (obj)=>obj.value
ipt.oninput = debounce(function(){
    console.log(co(this))
},1000)

感覺就挺憨的!形病!

節(jié)流客年,原理差不多,都是操控時(shí)間

好比你打游戲的技能冷卻窒朋,亦或是你等的公交車搀罢,總是多少時(shí)間來一趟蝗岖,如何控制時(shí)間有倆種說法侥猩,可以通過當(dāng)前時(shí)間減去上一次時(shí)間,也可以通過設(shè)置的時(shí)間去操作抵赢,兩種思路都可以

我們先按照防抖的思路寫一個(gè)setTimeout版本欺劳,老樣子 先返回一個(gè)函數(shù)唧取,有了前面的基礎(chǔ),現(xiàn)在節(jié)奏快點(diǎn)

function throttle(fn,delay){
    return function(){
        setTimeout(()=>{
            fn.apply(this,arguments)
        },delay)
    }
}

然后我們?nèi)プ鲆幌驴刂?/p>

function throttle(fn, delay) {
    //開啟一個(gè)值 默認(rèn)關(guān)閉
    let timer = false
    return function () {
        //如果這個(gè)timer是開啟的 那么說明我們?cè)跁r(shí)間范圍之外 那我們不做啥 直接返回
        if (timer) {
            return
        }
        else {
            //開啟這個(gè)值
            timer = true
            setTimeout(() => {
                fn.apply(this, arguments)
                //說明下一次可以執(zhí)行了 那你就繼續(xù)false吧
                timer = false
            }, delay)
        }

    }
}

window.addEventListener('resize', throttle(watchresize, 2000))

然后你發(fā)現(xiàn)在一直操作窗口的時(shí)候划提,2s觸發(fā)一次咯

    function throttle(fun, delay) {
        let previous = 0;
        return function () {
            let now = Date.now();
            let args = arguments;
            if (now - previous > delay) {
                func.apply(this, args);
                previous = now;
            }
        }
    }

也可以使用時(shí)間戳去控制7愕堋! 看完嘗試自己再手寫幾遍就應(yīng)該可以理解了

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末鹏往,一起剝皮案震驚了整個(gè)濱河市淡诗,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌伊履,老刑警劉巖韩容,帶你破解...
    沈念sama閱讀 216,402評(píng)論 6 499
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異唐瀑,居然都是意外死亡群凶,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,377評(píng)論 3 392
  • 文/潘曉璐 我一進(jìn)店門哄辣,熙熙樓的掌柜王于貴愁眉苦臉地迎上來请梢,“玉大人,你說我怎么就攤上這事力穗∫慊。” “怎么了?”我有些...
    開封第一講書人閱讀 162,483評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵当窗,是天一觀的道長(zhǎng)形真。 經(jīng)常有香客問我,道長(zhǎng)超全,這世上最難降的妖魔是什么咆霜? 我笑而不...
    開封第一講書人閱讀 58,165評(píng)論 1 292
  • 正文 為了忘掉前任,我火速辦了婚禮嘶朱,結(jié)果婚禮上蛾坯,老公的妹妹穿的比我還像新娘。我一直安慰自己疏遏,他們只是感情好脉课,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,176評(píng)論 6 388
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著财异,像睡著了一般倘零。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上戳寸,一...
    開封第一講書人閱讀 51,146評(píng)論 1 297
  • 那天呈驶,我揣著相機(jī)與錄音,去河邊找鬼疫鹊。 笑死袖瞻,一個(gè)胖子當(dāng)著我的面吹牛司致,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播聋迎,決...
    沈念sama閱讀 40,032評(píng)論 3 417
  • 文/蒼蘭香墨 我猛地睜開眼脂矫,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來了霉晕?” 一聲冷哼從身側(cè)響起庭再,我...
    開封第一講書人閱讀 38,896評(píng)論 0 274
  • 序言:老撾萬榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎牺堰,沒想到半個(gè)月后佩微,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,311評(píng)論 1 310
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡萌焰,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,536評(píng)論 2 332
  • 正文 我和宋清朗相戀三年哺眯,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片扒俯。...
    茶點(diǎn)故事閱讀 39,696評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡奶卓,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出撼玄,到底是詐尸還是另有隱情夺姑,我是刑警寧澤,帶...
    沈念sama閱讀 35,413評(píng)論 5 343
  • 正文 年R本政府宣布掌猛,位于F島的核電站盏浙,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏荔茬。R本人自食惡果不足惜废膘,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,008評(píng)論 3 325
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望慕蔚。 院中可真熱鬧丐黄,春花似錦、人聲如沸孔飒。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,659評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)坏瞄。三九已至桂对,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間鸠匀,已是汗流浹背蕉斜。 一陣腳步聲響...
    開封第一講書人閱讀 32,815評(píng)論 1 269
  • 我被黑心中介騙來泰國(guó)打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人蛛勉。 一個(gè)月前我還...
    沈念sama閱讀 47,698評(píng)論 2 368
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像睦柴,于是被迫代替她去往敵國(guó)和親诽凌。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,592評(píng)論 2 353

推薦閱讀更多精彩內(nèi)容