函數(shù)防抖和函數(shù)節(jié)流

函數(shù)防抖和函數(shù)節(jié)流

函數(shù)防抖和函數(shù)節(jié)流:是優(yōu)化高頻率執(zhí)行的JavaScript代碼的一種手段伶跷。常用于JavaScript中的一些事件壳炎,如瀏覽器的resize那婉、scroll眯娱,鼠標(biāo)的mousemove斑鸦、mouseover胖烛,鍵盤的keypress等临扮。例如input輸入框的keypress事件在觸發(fā)時毡咏,會不斷地調(diào)用綁定在事件上的回調(diào)函數(shù)陋率,極大地浪費(fèi)資源球化,降低前端性能。為了優(yōu)化體驗瓦糟,就需要對這類事件進(jìn)行調(diào)用次數(shù)的限制筒愚。

函數(shù)防抖(debounce)

所謂防抖,就是指觸發(fā)事件后在 n 秒內(nèi)函數(shù)只能執(zhí)行一次菩浙,如果在 n 秒內(nèi)又觸發(fā)了事件巢掺,則會重新計算函數(shù)執(zhí)行時間。防抖函數(shù)分為非立即執(zhí)行版和立即執(zhí)行版:

非立即執(zhí)行版:

//非立即執(zhí)行版的意思是觸發(fā)事件后函數(shù)不會立即執(zhí)行劲蜻,而是在 n 秒后執(zhí)行陆淀,如果在 n 秒內(nèi)又觸發(fā)了事件,則會重新計算函數(shù)執(zhí)行時間先嬉。

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);
    }
}

立即執(zhí)行版:

//立即執(zhí)行版的意思是觸發(fā)事件后函數(shù)會立即執(zhí)行轧苫,然后 n 秒內(nèi)不觸發(fā)事件才能繼續(xù)執(zhí)行函數(shù)的效果。

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)
    }
}

封裝版本:

/**
 * @desc 函數(shù)防抖
 * @param func 函數(shù)
 * @param wait 延遲執(zhí)行毫秒數(shù)
 * @param immediate true 表立即執(zhí)行坝初,false 表非立即執(zhí)行
 */
function debounce(func,wait,immediate) {
    let timeout;

    return function () {
        let context = this;
        let args = arguments;

        if (timeout) clearTimeout(timeout);
        if (immediate) {
            var callNow = !timeout;
            timeout = setTimeout(() => {
                timeout = null;
            }, wait)
            if (callNow) func.apply(context, args)
        }
        else {
            timeout = setTimeout(function(){
                func.apply(context, args)
            }, wait);
        }
    }
}


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

所謂節(jié)流浸剩,就是指連續(xù)觸發(fā)事件但是在 n 秒中只執(zhí)行一次函數(shù)。節(jié)流會稀釋函數(shù)的執(zhí)行頻率鳄袍。

對于節(jié)流绢要,一般有兩種方式可以實現(xiàn),分別是時間戳版和定時器版拗小。

時間戳版:

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

定時器版:

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)
        }
    }
}

時間戳版和定時器版的節(jié)流函數(shù)的區(qū)別就是重罪,時間戳版的函數(shù)觸發(fā)是在時間段內(nèi)開始的時候,而定時器版的函數(shù)觸發(fā)是在時間段內(nèi)結(jié)束的時候哀九。

封裝版本:

/**
 * @desc 函數(shù)節(jié)流
 * @param func 函數(shù)
 * @param wait 延遲執(zhí)行毫秒數(shù)
 * @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)
            }
        }
    }
}

案例

div 元素綁定了 mousemove 事件,當(dāng)鼠標(biāo)在 div(灰色)區(qū)域中移動的時候會持續(xù)地去觸發(fā)該事件導(dǎo)致頻繁執(zhí)行函數(shù)阅束。

<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 = debounce(count,1000,true );
    //節(jié)流
    content.onmousemove = throttle(count,1000,1 );
</script>

參考

輕松理解防抖和節(jié)流

徹底弄懂函數(shù)防抖和函數(shù)節(jié)流

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末呼胚,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子息裸,更是在濱河造成了極大的恐慌蝇更,老刑警劉巖沪编,帶你破解...
    沈念sama閱讀 221,576評論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異年扩,居然都是意外死亡蚁廓,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,515評論 3 399
  • 文/潘曉璐 我一進(jìn)店門厨幻,熙熙樓的掌柜王于貴愁眉苦臉地迎上來相嵌,“玉大人,你說我怎么就攤上這事况脆》贡觯” “怎么了?”我有些...
    開封第一講書人閱讀 168,017評論 0 360
  • 文/不壞的土叔 我叫張陵漠另,是天一觀的道長捏雌。 經(jīng)常有香客問我,道長笆搓,這世上最難降的妖魔是什么性湿? 我笑而不...
    開封第一講書人閱讀 59,626評論 1 296
  • 正文 為了忘掉前任,我火速辦了婚禮满败,結(jié)果婚禮上肤频,老公的妹妹穿的比我還像新娘。我一直安慰自己算墨,他們只是感情好宵荒,可當(dāng)我...
    茶點故事閱讀 68,625評論 6 397
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著净嘀,像睡著了一般报咳。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上挖藏,一...
    開封第一講書人閱讀 52,255評論 1 308
  • 那天暑刃,我揣著相機(jī)與錄音,去河邊找鬼膜眠。 笑死岩臣,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的宵膨。 我是一名探鬼主播架谎,決...
    沈念sama閱讀 40,825評論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼辟躏!你這毒婦竟也來了谷扣?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,729評論 0 276
  • 序言:老撾萬榮一對情侶失蹤捎琐,失蹤者是張志新(化名)和其女友劉穎抑钟,沒想到半個月后涯曲,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 46,271評論 1 320
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡在塔,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 38,363評論 3 340
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了拨黔。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片蛔溃。...
    茶點故事閱讀 40,498評論 1 352
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖篱蝇,靈堂內(nèi)的尸體忽然破棺而出贺待,到底是詐尸還是另有隱情,我是刑警寧澤零截,帶...
    沈念sama閱讀 36,183評論 5 350
  • 正文 年R本政府宣布麸塞,位于F島的核電站,受9級特大地震影響涧衙,放射性物質(zhì)發(fā)生泄漏哪工。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,867評論 3 333
  • 文/蒙蒙 一弧哎、第九天 我趴在偏房一處隱蔽的房頂上張望雁比。 院中可真熱鬧,春花似錦撤嫩、人聲如沸偎捎。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,338評論 0 24
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽茴她。三九已至,卻和暖如春程奠,著一層夾襖步出監(jiān)牢的瞬間丈牢,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,458評論 1 272
  • 我被黑心中介騙來泰國打工梦染, 沒想到剛下飛機(jī)就差點兒被人妖公主榨干…… 1. 我叫王不留赡麦,地道東北人。 一個月前我還...
    沈念sama閱讀 48,906評論 3 376
  • 正文 我出身青樓帕识,卻偏偏與公主長得像泛粹,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子肮疗,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 45,507評論 2 359

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