我正在嘗試重新實作 redux compose函式,而不是使用reduce我使用 for 回圈,這是我的代碼:
function compose(...funcs) {
if (funcs.length === 0) {
return (arg) => arg;
}
if (funcs.length === 1) {
return funcs[0];
}
let result;
for (let i = funcs.length - 1; i > -1; i--) {
result = result
? (...args) => funcs[i](result(...args))
: (...args) => funcs[i](...args);
}
return result;
}
// test
function fn1(x) {
return x 1;
}
function fn2(x) {
return x * 10;
}
function fn3(x) {
return x - 1;
}
console.log(compose(fn3, fn2, fn1)(10)); // 109
由于 (10 1) * 10 - 1 是 109,因此預計會記錄 109,但是它給了我這樣的錯誤:
RangeError: Maximum call stack size
看起來我正在做一些遞回,但我所做的只是一個 for 回圈,不知道我的代碼的問題在哪里?
uj5u.com熱心網友回復:
我認為這個問題就像下面的例子:
a = () => 2;
a = () => 3 * a();
console.log(a);
// this prints () => 3 * a() in console
// so when you call a(), it will call 3 * a(), which will again call 3 * a() and so on
// leading to infinite recursion
bind我的解決方案基于此參考鏈接使用函式略有不同: https ://stackoverflow.com/a/6772648/4688321 。
我認為bind創建函式的新副本result并將其系結到新物件。不使用bind會導致遞回,因為這樣代碼就變成了上面的例子,result呼叫result。
function compose(...funcs) {
if (funcs.length === 0) {
return (arg) => arg;
}
if (funcs.length === 1) {
return funcs[0];
}
let result;
for (let i = funcs.length - 1; i > -1; i--) {
if (i == funcs.length - 1)
result = (...args) => funcs[i](...args);
else {
let temp = result.bind({});
result = (...args) => funcs[i](temp(...args));
}
}
return result;
}
// test
function fn1(x) {
console.log("fn1");
return x 1;
}
function fn2(x) {
console.log("fn2");
return x * 10;
}
function fn3(x) {
console.log("fn3");
return x - 1;
}
//console.log(compose(fn3, fn2, fn1));
let ret = compose(fn3, fn2, fn1);
console.log(ret(10)); // 109
uj5u.com熱心網友回復:
與其在 時嘗試組合函式,不如在呼叫compose結果函式時組合它們似乎要容易得多:
function compose(...funcs) {
if (funcs.length === 0) {
return (arg) => arg
}
return function (...args) {
let result = funcs .at (-1) (...args)
for (let i = funcs.length - 2; i > -1; i--) {
result = funcs [i] (result)
}
return result
}
}
// test
function fn1(x) {
return x 1;
}
function fn2(x) {
return x * 10;
}
function fn3(x) {
return x - 1;
}
console.log(compose(fn3, fn2, fn1)(10)); // 109
然而,再一次,reduce實作一個更干凈的實作:
const compose = (...fns) => (arg) =>
fns .reduceRight ((a, fn) => fn (a), arg)
或者如果你想讓最右邊的函式接收多個變數,那么
const compose = (...fns) => (...args) =>
fns .reduceRight ((a, fn) => [fn (...a)], args) [0]
轉載請註明出處,本文鏈接:https://www.uj5u.com/caozuo/417789.html
標籤:
