函數柯里化實現sum函數

需求

實現sum函數,使其可以傳入不定長參數,以及不定次數調用

//示例
console.log(sum(1,2)(3)())   //6
console.log(sum(2,3,4,5)(1,2)(3)(4)())    //23

需求分析

實現sum函數我們可以考慮可以使用閉包的形式來實現

  1. 因為每次傳參,所以我們不知道這是不是最後一次,如果是最後一個括號,則就要執行

  2. 我們可以通過每次調用時對傳入參數的個數來判斷目前是否是最後一個括號

  3. 如果有參數就說明是調用,那麼我們就將參數保存到外面的容器中

  4. 如果沒有參數則說明是調用

  5. 如果最後是調用時,我們只需要將所有的參數累加即可

function add (...args) {
  return args.reduce((pre, cur) => pre + cur)
}
function currying (fn) {
  // 作為參數存儲的容器
  let argArr = []
  // 中間容器,用來判斷傳入是否有傳入參數
  return function temp (...arg) {
    // 只要傳入的參數不為0,就繼續將參數交給容器
    if (arg.length) {
      // 使用擴展運算符,將result中的值進行更新
      argArr = [...argArr, ...arg]
      return temp
    }
    // 如果沒有參數的話則說明是最後一個括號,也就是執行
    else {
      let val = fn(...argArr)
      argArr = []
      return val
    }
  }
}

let sum = currying(add)
console.log(sum(1, 2, 3, 4)(1)())  //15
console.log(sum(1,2)(3)())  //6

reduce回顧

reduce數組方法,接收兩個參數,第一個為一個累加器函數,第二個參數為初始值
比如對數組累加,我們如果不設置初始值,也就是不設置第二個參數,那麼累加器中
第一個參數pre就是數組的第一個元素,cur就是第二個元素,也就是第一次就會訪問到
數組的第一個和第二個元素
如果傳遞了初始值,那麼數組索引就會從0開始,也就是第一個cur是數組第一個元素,
pre為傳遞的初始值
通俗一點來說:

如果不寫初始值,那麼元素累加就從索引為1開始,初始值默認為數組第一個元素
寫上初始值就從索引為0開始。
累加函數有四個參數(preValue,curValue,index,arr)
每一項都要有一個返回值

閉包回顧

閉包的一般形式就是函數返回函數,在內層函數中可以訪問外層函數中的變量
這樣可以延長變量的作用域,使得變量可以長期保存。比如我們在這個案例中使用閉包
來保存每次傳遞的參數。閉包可能會造成內存泄露,其它造成內存泄漏的場景還有:

  • 沒有被清理的定時器
  • 意外的全局變量
  • 沒有清理對DOM的引用