![](/img/trans.png)
[英]How Array.reduce put functions as parameters in function composition?
[英]How Javascript `reduce` performed on function array achieves function composition?
我在redux
compose
功能中遇到了這種模式。 我仍然不明白如何在下面的示例中從最后開始而不是從第一個開始評估函數:
function f2(a) {
return a + a;
}
function f3(a) {
return a + a + a;
}
function f4(a) {
return a + a + a + a;
}
function f5(a) {
return a + a + a + a + a;
}
function compose(...funcs) {
return funcs.reduce(function x(a, b) {
return function y(...args) {
const temp = a(b(...args));
return temp;
};
});
}
const composedFunction = compose(f2, f3, f4, f5);
const result = composedFunction(2);
在第一個reduce
迭代中,累加器為f2
因此我們得到f2(f3(2))=12
。 在下一次迭代中,我們將調用f4(12)=48
。 在上一次迭代中,我們將調用f5(48)=240
。 因此,評估順序為f5(f4(f2(f3(2))))
。 但是使用console.log
我看到評估順序是f2(f3(f4(f5(2))))
,巧合的也是240。
據我了解,函數y
是為所有數組元素調用的,那么為什么只有最后一個函數將2
作為參數?
讓我們通過一個非常簡單的示例逐步完成代碼:
compose(f2, f3, f4)
由於沒有傳遞任何初始值來減少值,因此它將以數組的第一個(f2)和第二個(f3)值開頭,並以該值調用回調, x
的調用為a
為f2
, b
為f3
。 現在x
不執行任何操作,只返回可以通過閉包訪問a和b的函數y
。
Reduce現在將繼續到第三個元素,第一個參數是上一個回調(閉包y
)的結果,第二個參數是f4
。 現在再次調用x
,並在y
上創建另一個閉包, y
從整個函數中最終返回。
如果我們嘗試可視化這樣的閉包函數,它將是:
y { // closure of y
a -> y { // a references another closure of y
a -> f3,
b -> f2
},
b -> f4
}
現在,您調用該閉包y
並將2傳遞給它,這將調用b
( f4
)並將結果傳遞給該調用到a
(閉包y)。
a ( b(...args))
y { ... } ( f4(2) )
現在,封閉的y將執行相同的操作:
a ( b ( ...args))
f2( f3( f4( 2 ) ) )
提示:有時很難跟蹤閉包的值,因此控制台為您提供了強大的實用程序來跟蹤它們:在控制台的“ debugger”選項卡中打開代碼,單擊函數調用所在的行號。附加斷點,然后再次運行代碼,只要到達斷點,執行就會產生,您可以看到所有變量(包括封閉變量)的值。
reduce不會調用函數f2,f3,f3,f5,而是從這些函數創建函數。 這是每次迭代中累加器的值。 請注意,該值是一個function
而不是function
執行的結果。
1:a = f2; b = f3;返回值(不是溫度,但函數y)= f2(f3(... args))
2:a(上一個返回值)= f2(f3(... args)); b = f4;返回值= f2(f3(f4(... args))))
等等....
撰寫功能可以重寫為:
function compose(...funcs) {
return funcs.reduce(function (a, b) {
return function (arg) {
const temp = a(b(arg));
return temp;
};
});
}
第一次迭代后,作為下一個累加器傳遞的返回函數為:
function (arg) { // R1
return f2(f3(arg));
}
在第二次迭代之后,作為下一個累加器傳遞的返回函數為:
function (arg) { // R2
return R1(f4(arg));
}
最后,分配給compositionFunction的返回函數為:
function (arg) { // composedFunction
return R2(f5(arg));
}
因此,運行composedFunction(2)
並返回上鏈:
f5(2) returns 10
R2(10) returns R1(f4(10))
which is R1(40)
R1(40) returns f2(f3(40))
which is f2(120)
which is 240
希望這足夠了。
可以將其寫為以下單個調用:
function composedFunction(arg) {
return f2(f3(f4(f5(arg))));
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.