你有沒(méi)有遇到過(guò)這種情況:某個(gè)函數(shù)被柯里化(Currying)了,調(diào)用方式變成了fn(a)(b)(c)
,但你突然想讓它變回普通的fn(a, b, c)
?這時(shí)候,反柯里化就是你的救星!
1. 先說(shuō)說(shuō)柯里化是啥(復(fù)習(xí)一下)
柯里化是把一個(gè)多參數(shù)函數(shù)變成一連串單參數(shù)函數(shù)的過(guò)程。比如:
function add(a, b) {
return a + b;
}
function curriedAdd(a) {
return function(b) {
return a + b;
};
}
console.log(add(1, 2));
console.log(curriedAdd(1)(2));
柯里化好用,但有時(shí)候我們拿到一個(gè)柯里化函數(shù),卻希望它能像普通函數(shù)一樣調(diào)用。這時(shí)候就需要反柯里化!
2. 反柯里化:讓函數(shù)"反悔"
反柯里化的本質(zhì)是:把一個(gè)柯里化函數(shù)還原成普通的多參數(shù)函數(shù)。
舉個(gè)??,假設(shè)我寫了一個(gè)柯里化的乘法函數(shù):
function curriedMultiply(a) {
return function(b) {
return a * b;
};
}
const multiply = curriedMultiply;
但現(xiàn)在我想讓它能直接multiply(2, 3)
調(diào)用,怎么辦?
方案1:手動(dòng)反柯里化
function uncurry(fn) {
return function(a, b) {
return fn(a)(b);
};
}
const normalMultiply = uncurry(curriedMultiply);
console.log(normalMultiply(2, 3));
方案2:通用反柯里化函數(shù)
如果不知道函數(shù)被柯里化了幾層,可以寫一個(gè)更通用的版本:
function uncurry(fn) {
return function(...args) {
let currentFn = fn;
for (const arg of args) {
if (typeof currentFn !== 'function') {
throw new Error('參數(shù)過(guò)多,無(wú)法繼續(xù)調(diào)用!');
}
currentFn = currentFn(arg);
}
return currentFn;
};
}
const curriedAddThree = a => b => c => a + b + c;
const normalAdd = uncurry(curriedAddThree);
console.log(normalAdd(1, 2, 3));
3. 我踩過(guò)的坑:第三方庫(kù)的柯里化函數(shù)
去年我用一個(gè)工具庫(kù)時(shí)遇到了這個(gè)問(wèn)題。庫(kù)里的某個(gè)API是這樣的:
const fetchData = (url) => (params) => (options) => {
return fetch(url, { ...params, ...options });
};
每次調(diào)用都得寫fetchData('/api')({ id: 1 })({ timeout: 5000 })
,太麻煩了!
于是我祭出反柯里化大法:
const normalFetchData = uncurry(fetchData);
normalFetchData('/api', { id: 1 }, { timeout: 5000 });
4. 什么時(shí)候用反柯里化?
- 適配第三方庫(kù):當(dāng)庫(kù)的API是柯里化風(fēng)格,但你想用普通調(diào)用方式時(shí)
- 代碼重構(gòu):團(tuán)隊(duì)決定不再使用柯里化,需要批量改造舊代碼
- 提高可讀性:某些場(chǎng)景下直接傳多個(gè)參數(shù)更直觀
5. 反柯里化的局限性
- 參數(shù)長(zhǎng)度必須固定:如果柯里化函數(shù)允許部分應(yīng)用(如
fn(a)(b)
和fn(a)(b)(c)
混用),反柯里化會(huì)失效 - 性能影響:多了一層函數(shù)調(diào)用,但對(duì)大多數(shù)場(chǎng)景影響微乎其微
總結(jié)
- 柯里化是好東西,但有時(shí)候我們需要讓函數(shù)"回歸普通"
- 反柯里化就是把
fn(a)(b)(c)
變回fn(a, b, c)
的技術(shù) - 特別適合處理第三方庫(kù)的柯里化API
?轉(zhuǎn)自https://juejin.cn/post/7512284328867495948
該文章在 2025/6/6 9:15:46 編輯過(guò)