之所以称为简化器,是因为它是传递给函数的类型
Array.prototype.reduce(reducer, ?initialValue)
这对我来说没有多大意义。有人可以向我解释为什么它们实际上称为减速器吗?它们返回默认值(或具有默认参数值)的事实并不会使它们归约。
Answers:
它们返回默认值(或具有默认参数值)的事实并不会使它们归约。
减速器不仅仅返回默认值。它们总是返回状态的累积(基于所有先前和当前的动作)。
因此,它们充当状态的减少者。每次调用redux reducer时,都会通过action传递状态(state, action)
。然后,根据操作减少(或累积)该状态,然后返回下一个状态。这是经典fold
或reduce
功能的一个循环。
正如@azium总结的那样state -> action -> state
。
如果您将应用程序中的一系列操作视为列表,或者更像是流,则可能更有意义。
举这个人为的例子:
['apple', 'banana', 'cherry'].reduce((acc, item) => acc + item.length, 0)
第一个参数是形式的函数(Int, String) => Int
。连同初始值一起,传递reduce
可能称为“归约函数”的值,并获得处理一系列项目的结果。因此,您可能会说,化简函数描述了如何对每个连续的单独项目进行更改以更改结果。换句话说,reducer函数获取先前的输出和下一个值,并计算下一个输出。
这类似于Redux reducer的操作:它采用上一个状态和当前操作,并计算下一个状态。
在真正的函数式编程风格中,您可以从概念上消除应用于自变量和结果的含义,而只关注输入和输出的“形状”。
在实践中,Redux减速器通常是正交的,这意味着对于给定的动作,它们都不会全部更改相同的属性,这使得轻松划分职责并使用汇总输出combineReducers
。
之所以将redux reducer称为a
reducer
是因为您可以“减少” (商店中的)acollection of actions
和aninitial state
,以便在其上执行这些操作以获得结果final state
。
怎么样?为了回答这个问题,让我再次定义一个减速器:
的减少()方法施加
function (reducer)
针对accumulator
与阵列的每个值(从左到右),以将其降低到一个值。
Redux减速器有什么作用?
减速器是
function
采用当前状态和操作并返回下一个状态的纯函数。请注意,状态是accumulated
应用集合上的每个操作来更改此状态的状态。
因此,给定a collection of actions
,将缩减器应用于集合的每个值(从左到右)。第一次返回initial value
。现在,将reducer再次应用于此初始状态和返回下一个状态的第一个操作。每次都会在上应用下一个收集项(操作)current state
以获取next state
直到到达数组末尾。然后,您得到the final state
。多么酷啊!
作者认为状态是reduce函数的累加器。例如:
Final State = [Action1, Action2, ..., ActionN].reduce(reducer, Initial State);
reduce函数来自Functional Programming,名称“ reducer”也来自FP。
我不喜欢在这里使用这个名字。因为我不认为世界是行动后的单一价值结果。这里的状态是一个对象。例如:
['eat', 'sleep'] === [addTodo('eat'), addTodo('sleep')].reduce(reducer, []);
该减速器完全不减少任何东西。而且我不在乎它是否会减少任何东西。将其命名为Transducer会更有意义。
从现在开始,我们称其为演绎器怎么样。它根据先前的状态和传入的动作推导新的状态。
我不太清楚Redux缩减器如何直接映射到您使用的函数reduce
,因此这里有一些示例来说明它们如何匹配。
首先是MDN Array.reduce文档中的标准reducer(在MDN中称为“累加器”)功能,然后是Dan AbramovCounter.js
在“您可能不需要Redux”博客文章末尾的简化示例。
sum
向累加器添加一个值 reducer
向累加器添加/减去一个值。在这两种情况下,“状态”都只是一个整数。
您正在将操作“累积”到状态中。这也是修改任何JavaScript对象的不变方法。
const sum = function(acc, val) {
return acc + val;
};
const reducer = function(state, action) {
switch (action) {
case 'INCREMENT':
return state + 1;
case 'DECREMENT':
return state - 1;
default:
return state;
}
};
console.log('sum', [1, -1, 1].reduce(sum, 0));
console.log('reduce', ['INCREMENT', 'DECREMENT', 'INCREMENT'].reduce(reducer, 0));
console.log('sum', [1, 1, 1].reduce(sum, 0));
console.log('reduce', ['INCREMENT', 'INCREMENT', 'INCREMENT'].reduce(reducer, 0));
其他答案很好地解释了为何如此命名,但让我们尝试命名更多内容...
const origState = 0;
const actionOperators = {
increment: (origState) => origState++,
decrement: (origState) => origState--,
};
const anOperator = (aState, anAction) => actionOperators[anAction](aState);
const actions = ['increment', 'decrement', 'increment'];
const finalState = actions.reduce(anOperator, origState);
首先,reduce
可以称为use anOperator with every action name and accumulated state, starting with origState
。在Smalltalk中,它称为actions inject: origState into: anOperator
。但是您实际上向操作员注入了什么?origState和操作名称。因此,即使在Smalltalk中,方法名称也不是很清楚。
actionOperators[increment]
是Reducer,但我宁愿将其称为actionOperator,因为它是为每个操作实现的。状态只是一个参数(另一个是返回值)。
然而,Reducer是在Google搜索结果之上的一个更好的词。它也与Redux类似。
在下面的这段代码中,您只需要将累加器视为动作,并将currentValue视为redux上下文中的状态。在此示例中,您将找到为什么他们也将其命名为减速器。
const array1 = [1, 2, 3, 4];
const reducer = (accumulator, currentValue) => accumulator + currentValue;
// Main operation is 1 + 2 + 3 + 4 = 10
// but think of it as a stack like this:
// | 2 | | 3 | | 4 |
// |_1_| |_3_| |_6_| | 10 | => the 10 is in result
console.log(array1.reduce(reducer));
// expected output: 10
reduce()方法在数组的每个元素上执行reducer函数(由您提供),从而产生单个输出值。
reduce
,该函数可以访问默认值和另一个值,并为您提供可能转换后的默认值。state -> action -> state