js實現參數定長/不定長的柯里化


文章原文: https://www.cnblogs.com/yalong/p/14298085.html

題目1:把一個計算加法的函數fn 進行柯里化,其中fn 分為 參數個數固定 和 參數個數不固定兩種

參數個數固定的柯里化實現:

  function fn(a, b, c) {
    return a + b + c
  }
  function curry(fn) {
    // 獲取原函數的參數長度
    const argLen = fn.length;
    // 保存預置參數, 當預置參數 有三個的時候 直接返回了函數,需要單獨執行一次
    const presetArgs = [].slice.call(arguments, 1)
    // 返回一個新函數
    return function() {
      // 新函數調用時會繼續傳參
      const restArgs = [].slice.call(arguments)
      const allArgs = [...presetArgs, ...restArgs]
      if (allArgs.length >= argLen) {
        // 如果參數夠了,就執行原函數
        return fn.apply(null, allArgs)
      } else {
        // 否則繼續柯里化
        return curry.call(null, fn, ...allArgs)
      }
    }
  }

  // 用例一
  let c1 = curry(fn, 1);
  let c2 = curry(c1, 2);
  let c3 = curry(c2, 3);
  console.log(c3()) // 6

  // 用例二
  let curried = curry(fn);
  console.log(curried(1, 2, 3)) // 6
  console.log(curried(1, 2)(3)) // 6
  console.log(curried(1)(2, 3)) // 6
  console.log(curried(1)(2)(3)) // 6

  // 用例三
  // 注意這個, 因為初始的時候 把參數全部傳進去了,導致返回的是一個函數, 沒能走到 apply 的立即執行
  console.log(curry(fn, 1, 2, 3)()) // 6
  console.log(curry(fn, 1, 2)(3)) // 6
  console.log(curry(fn, 1)(2, 3)) // 6
  console.log(curry(fn, 1)(2)(3)) // 6

參數個數不固定的柯里化實現

 function curry(fn) {
  // 保存預置參數
  const presetArgs = [].slice.call(arguments, 1)
  // 返回一個新函數
  function curried () {
    // 新函數調用時會繼續傳參
    const restArgs = [].slice.call(arguments)
    const allArgs = [...presetArgs, ...restArgs]
    // 下面這個相當於 return currl(fn, ...allArgs)
    return curry.call(null, fn, ...allArgs)
  }
  // 重寫toString
  curried.toString = function() {
    return fn.apply(null, presetArgs)
    // 下面這個是一樣的
    // return fn.call(null, ...presetArgs)
  }
  return curried;
}

function fn() {
  return [...arguments].reduce((prev, curr) => {
    return prev + curr
  }, 0)
}
var add = curry(fn);
console.log(add(1)(2)(3)(4)) // 10
console.log(add(1, 2)(3, 4)(5, 6)) // 21

題目2: 實現add(1)(2)(3)(4)的打印結果為10,並且要求可以隨意調用,不過每次只傳一個參數,如add(1)(2)(3)(4)(5)的打印結果為15
實現代碼如下:

function add(x) {
    let sum = x;
    let tmp = function (y) {
        sum = sum + y;
        return tmp;
    };
    tmp.toString = function () {
        return sum;
    };
    return tmp;
}
console.log(add(1)(2)(3)) // 6
console.log(add(1)(2)(3)(4)) // 10
console.log(add(1)(2)(3)(4)(5)) // 15

題目3: 實現add(1, 2)(3)的打印結果為6,add(1)(2, 3, 4)(5) 結果為15, 意思就是 傳遞的參數個數不固定
實現代碼如下:

function add () {
    let args = [...arguments];
    let fn = function () {
        args.push(...arguments);
        return fn
    }
    fn.toString=function(){
        return args.reduce((a, b) => {
            return a + b
        })
    }
    return fn
}
console.log(add(1, 2)(3)) // 6
console.log(add(1)(1,2,3)(2)) // 9
console.log(add(1)(2, 3, 4)(5)) // 15

上面用到了toString 這里就聯想到了valueOf 這兩者的區別簡單來說如下:

  • valueOf():返回最適合該對象類型的原始值
  • toString(): 將該對象的原始值以字符串形式返回

這兩個方法一般是交由JS去隱式調用,以滿足不同的運算情況。
在數值運算里,會優先調用valueOf(),如a + b
在字符串運算里,會優先調用toString(),如alert(c)。
當然更深入的說法還有,不過這里就不討論了。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM