文章原文: 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)。
當然更深入的說法還有,不過這里就不討論了。