let's have a look how reduce work and what it does.
I haven't had a look the native reduce function but it would be similar to the following.
Array.prototype.reduce = function(fn,initial = 0){
let i = 0;
let accumulator = initial;
while(i<this.length){
accumulator = fn(accumulator,this[i++]);
}
return accumulator;
}
Let's use this reduce function with the example from the MDN site you brought.
const array1 = [1, 2, 3, 4];
const reducer = (accumulator, currentValue) => accumulator + currentValue;
console.log(array1.reduce(reducer, 5));
// 5 + 1 + 2 + 3 + 4
//expected output: 15
If you look at the reduce function body,
this does the job
while(i<this.length){
accumulator = fn(accumulator,this[i++]);
}
it passes the accumulator value which returns from the callback function.
so the accumulator value would be changed something like the followings
- accumulator = 5(initial value) + 1(arr[0]) = 6
- accumulator = 6(accumulator from above) + 2(arr[1]) = 8
- accumulator = 8(accumulator from above) + 3(arr[2]) = 11
- accumulator = 11(accumulator from above) + 4(arr[3]) = 15
now the accumulator value is 15.
Let's move to the question you posted.
export function reduceReducers(...reducers) {
return (previous, current) =>
reducers.reduce(
(p, r) => r(p, current),
previous
);
}
So this is so called partial application or currying in functional programming.
As the name says you partially invoke the function.
This is a small example.
const myfamily = (lastName) => (firstName) => `${firstName} ${lastName}`;
const printName = myfamily("Kim");
const me = printName("Jack"); // console Jack Kim
const parnter = printName("Sarah");// console Sarah Kim
In this example, I want to print out our family members' full name.
so instead of writing repetitive surname, I invoke the myFamily function first passing surname and it returns another function which our surname is referenced inside the function body ( javascript closure ).
Using this technique, we can create a lot of interesting functions like once,debounce etc,
but this is out of our scope
Now, if we look at the reduceReducers function, the function signature looks identical to myFamily function.
It first accept reducers array and returns another function which expecting previous and current objects.
let's say we have the following reducers array
let reducers = [
function a(pre,cur){ return Object.assign(pre,{a:"This is a"},cur); },
function b(pre,cur){ return Object.assign(pre,{a:"This is new a",b:"This is
b"},cur); },
function c(pre,cur){ return Object.assign(pre,{c:"This is c",final:"This is
the last"},cur); }
];
we can call the reduceReducers function like this
const willbeReduced = reduceReducers.apply(null,reducers);
now we have willbeReduced function,
we can call it like this.
willbeReduced({pre:"This is previous"},{cur:"This is current"})
our state would be
{pre:'This is previous',
a:'This is new a',
cur:'This is current',
b:'This is b',
c:'This is c',
final:'This is the last'}
So previous and current are just plain objects.
previous is used for the initial object for reduce function
p and r
p is the accumulator value
r is each function from the reducers array
r expects two objects first accumulator and current object and returns new object ( new accumulator value )
Have a look at the reduce function signature again and reducers array