到底JS柯里化在專案中怎麼用?

可_可發表於2019-04-25

前言

[適合讀者]:有一定開發經驗的前端人員

之前在很多文章裡面看了柯里化的相關知識,大多舉的例子都是實現累加累乘這些的函式,然後具體專案裡面怎麼用,實際場景很少提到,總感覺看完之後好像理解了,又好像沒理解,可能主要還是沒有一個實際的真實運用場景導致我們理解起來很困難,接下來我嘗試寫一些柯里化在專案中的運用希望能幫助大家理解這個東西

柯里化

下面先說說柯里化的幾個特點,然後根據這幾個特點分別舉例來說明一下實際運用場景

  1. 提前返回
  2. 延遲執行
  3. 引數複用

提前返回

案例一(常見的相容性判斷程式碼)
  1. 封裝一個addEvent相容低版本IE的程式碼

這個是一個提前返回的經典案例,通過一個自執行函式來將if...else...判斷只執行一次,並返回了一個新的函式,那麼後續再次呼叫的時候就不會執行if...else...的判斷了,提升了程式碼效能。

      var addEvent = (function() {
        if (window.addEventListener) {
          return function(el, type, cb, bubbing) {
            el.addEventListener(
              type,
              function(e) {
                cb.call(el, e);
              },
              bubbing
            );
          };
        } else if (window.attachEvent) {
          return function(el, type, cb, bubbing) {
            el.attachEvent('on' + type, function() {
              cb.call(el, e);
            });
          };
        }
      })();

複製程式碼
  1. 封裝一個簡單的createXmlHttpRequest 方法

這個的原理同上

    var createXmlHttpRequest = (function() {
        var xmlHttp;
        if (window.XMLHttpRequest) {
          return function() {
            return new XMLHttpRequest();
          };
        } else if (window.ActiveXObject) {
          return function() {
            return new ActiveXObject('Msxml2.XMLHTTP');
          };
        }
      })();
複製程式碼

通過上述兩個案例,我們可以發現提前執行大多數場景應該是用在我們需要對不同終端做相容處理的場景上面,那麼總結下要觸發提前執行這個場景,需要滿足如下兩個條件:

  1. 函式中需要使用if...else...或者其他的分支判斷
  2. 返回結果是一個新的函式,而不是一個具體的值

注: 使用柯里化返回結果是一個值而不是函式的話個人覺得不太需要使用

延遲執行

案例一 (節流防抖函式)
  1. 封裝一個防抖函式,節流函式也是同樣的延遲執行的道理
    function debuonce(fn, time) {
        let timer;
        return function() {
          const _args = [].slice.call(arguments);
          clearTimeout(timer);
          timer = setTimeout(() => {
            fn.apply(this, _args);
          }, time);
        };
      }
複製程式碼
案例二(bind函式)
  1. 封裝一個bind函式 bind方法的作用是物件冒充,改變函式的作用域,但是和call和apply的區別就是其返回值是一個函式,並且呼叫後並不執行這個函式,下面是一個bind函式的簡單示例,未考慮new的情況。

詳細的bind函式可以參照這篇文章:www.cnblogs.com/moqiutao/p/…

    Function.prototype.bind = function(fn) {
        const args = [].slice.call(arguments, 1);
        const context = this;
        return function() {
          const _args = args.concat([].slice.call(arguments, 1));
          return context.apply(fn, _args);
        };
      };
複製程式碼

通過上述案例可以看出,一般觸發延遲執行場景,需要以下兩個條件:

  1. 返回一個新函式
  2. 新函式裡面有上面引用了外層函式作用域中的變數

引數複用

這個情況可以參考網上的累加累乘這些案例

總結

函式柯里化確實比較難懂,初學者需要大量實踐才能夠明白其中的原委,雖然柯里化會有一定的效能問題,不過大多數人的程式碼裡面效能問題基本上不會是因為使用了柯里化導致的,所以可以放心使用。

本篇先寫這些案例,後續會繼續補充相關案例~

如果讀者還有一些實際案例,歡迎留言,我會對文章進行修改補充~

參考文章

JS中的柯里化(currying):www.zhangxinxu.com/wordpress/2…

學會函式柯里化(curry):www.codercto.com/a/54607.htm…

相關文章