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

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

今天我們來搞一搞節流,防抖,柯里化和反柯里化吧,是不是一看這詞就覺得哎喲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);        
    }    
};

 

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