1. 程式人生 > >JS的防抖,節流,柯裏化和反柯裏化

JS的防抖,節流,柯裏化和反柯裏化

style bubuko 特點 info 清晰 false 保存參數 argument col

今天我們來搞一搞節流,防抖,柯裏化和反柯裏化吧,是不是一看這詞就覺得哎喲wc,有點高大上啊。事實上,我們可以在不經意間用過他們但是你卻不知道他們叫什麽,沒關系,相信看了今天的文章你會有一些收獲的

節流

  首先我們來搞一下節流,啥叫節流,就是將高頻率觸發事件變成低頻率觸發事件,舉個簡單的例子,但我們用window.onscroll滾動事件的時候你會發現滾輪滑動一次可能會觸發好多次事件,

  代碼:

        window.onscroll = function(){
            console.log("觸發")
        }

  結果:

    技術分享圖片

  我只是稍微滑動了一下子而已,就觸發了十次,這個觸發次數實在是過於頻繁,那我們有沒有什麽方法來解決這個問題呢?

  思路:我們可以給一個開關,用定時器控制開關的變化,只有當開關打開時我們才去觸發打印。

 核心代碼:

    var bStop = true;
    window.onscroll = function() {
        if(!bStop){
            return;
        }
        bStop = false;
        setTimeout(()=>{
            var t = document.documentElement.scrollTop || document.body.scrollTop;
            console.log(t);
            bStop 
= true; },300) }

原諒我直接給你們把代碼放上來了,你們就不用一句一句打了,直接拉下代碼去就可以run了,美滋滋啊

適用場景:1.onscroll()

     2.onresize()

     3.oninput()事件等等

防抖

  現在我們再來看一看防抖,簡單來說,防抖就是不關心中間過程,只關心最後的結果

  例如在滾動時,我們需要獲取滾動結束時的位置,此時我們並不關心滾動過程中發生了什麽,而僅僅只是想知道結束那一刻的狀態,那這個時候我們就可以用到防抖

  思路:在執行函數時先清除一個延時器,之後再創建一個延時器,這樣每次函數觸發都會將上一個延時器清除並且建立下一個延時器,中間過程的延時器根本不會被觸發,因為他剛創建好就被清除了,     只有最後一個延時器,由於沒有人來清除他,所以他會正常執行。

  可能我說的不是很透徹,沒關系,讓我直接上代碼好吧,代碼還是很簡潔清晰的

  核心代碼:

var timer = null;
 window.onscroll = function(){
     if(timer){
         clearTimeout(timer);
     }

     timer = setTimeout(()=>{
        var t = document.documentElement.scrollTop || document.body.scrollTop;
        console.log(t);
     },300)
 }

  

柯裏化

    接著我們來搞一搞柯裏化好吧,柯裏化是指將使用多個參數的函數轉換成一系列使用一個參數的函數的技術(又稱為部分求值),

    目的:為了縮小適用範圍,創建一個針對性更強的函數

  特點:1.提高了代碼的合理性,更重的它突出一種思想---降低適用範圍,提高針對性。
     2.對於一個已有函數,對其約定好其中的某些參數輸入,然後生成一個更有好的、更符合業務邏輯的函數。

 好處:1.提高針對性

    2.延遲執行(只有在最後一次才執行)

    3.固定易變因素

 現在我們直接上一個小小的例子,有一個廚師,要做飯,但是他的手下沒有把菜買齊,這樣,買一份原料,放在廚師廚房,再買一份,放在廚師廚房,等買齊了,叫廚師過來,好了,原料齊了,可以做飯了。這個時候,廚師利用原料,把飯做好。廚師就像一個函數,他有自己的功能(做飯),但是參數(原料)不齊,每次執行這個函數,在參數不齊的情況下,只能返回一個新的函數,這個新的函數已經內置了之前的參數,當參數齊了之後完成他本身的功能。

    舉一個柯裏化的小栗子,假設現在我們要按照柯裏化的思想實現 add(1,2,3)(1)(2)(3)(4,5,6)(7,8)() 對裏面所有的參數求和

    直接上代碼好吧

// add 函數柯裏化
function add(){
    //建立args,利用閉包特性,不斷保存arguments
    var args = [].slice.call(arguments);
       //方法一,新建_add函數實現柯裏化
    var _add = function(){
        if(arguments.length === 0){
            //參數為空,對args執行加法
            return args.reduce(function(a,b){return a+b});
        }else {
            //否則,保存參數到args,返回一個函數
            [].push.apply(args,arguments);
            return _add;
        }
    }
    //返回_add函數
    return _add;

思想:1.當參數的長度不為0時,存儲參數,

   2.當參數的長度為零時,計算所有參數的和

  

反柯裏化

  作用:在與擴大函數的適用性,使本來作為特定對象所擁有的功能的函數可以被任意對象所用.

  對反柯裏化更通俗的解釋可以是 函數的借用,是函數能夠接受處理其他對象,通過借用泛化、擴大了函數的使用範圍。

  下面放一個通用的柯裏化函數:  

var uncurrying= function (fn) {
    return function () {
        var args=[].slice.call(arguments,1);
        return fn.apply(arguments[0],args);        
    }    
};

以上內容由本人的一些體會和參考了網上一些大佬們的意見或文章寫成,仍有不足之處,請各位見諒,有問題請指出

  

JS的防抖,節流,柯裏化和反柯裏化