0

我正在学习 Web 开发的状态管理,并遇到了这个带有纯功能的 redux 教程,如下所示。然而声明:“action.todo.id = state.todos.length + 1;” 让我怀疑这个纯函数是……不纯的。请赐教,谢谢!

export function rootReducer(state: IAppState, action): IAppState {

    switch (action.type) {
        case ADD_TODO:
            action.todo.id = state.todos.length + 1;    
            return Object.assign({}, state, {
                todos: state.todos.concat(Object.assign({}, action.todo)),
                lastUpdate: new Date()
            })

        case TOGGLE_TODO:
            var todo = state.todos.find(t => t.id === action.id);
            var index = state.todos.indexOf(todo);
            return Object.assign({}, state, {
                todos: [
                    ...state.todos.slice(0, index),
                    Object.assign({}, todo, {isCompleted: !todo.isCompleted}),
                    ...state.todos.slice(index+1)
                ],
                lastUpdate: new Date()
            })
        case REMOVE_TODO:
            return Object.assign({}, state, {
                todos: state.todos.filter(t => t.id !== action.id),
                lastUpdate: new Date()
            })
        case REMOVE_ALL_TODOS:
            return Object.assign({}, state, {
                todos: [],
                lastUpdate: new Date()
            })
    }
    return state;
}
4

2 回答 2

2

TL; DR - 不,不是。

让我们检查一下纯函数的定义。来自维基百科:

在计算机编程中,纯函数是具有以下属性的函数:

  1. 对于相同的参数,它的返回值是相同的(本地静态变量、非本地变量、可变引用参数或来自 I/O 设备的输入流没有变化)。

  2. 它的评估没有副作用(没有局部静态变量、非局部变量、可变引用参数或 I/O 流的突变)。

尽管您的函数确实符合第二个条件,但使用new Date()- 使其不纯。

在您的情况下,其杂质的原因是每个函数调用的日期都不同 - 无论传递的参数如何。

为了使其纯净,您应该将日期作为附加参数传递,这将允许您对相同的输入具有相同的输出。

Zaptree 还提到改变您的项目 ID 的长度,即 action.todo.id = state.todos.length + 1不纯,因为它可能会影响引用它的其他方。

于 2019-05-15T13:14:24.213 回答
0

您非常正确地意识到以下代码是不纯的:

action.todo.id = state.todos.length + 1;

执行此操作的正确方法如下(像您一样使用 es5 语法):

var newTodo = Object.assign({}, action.todo, {
  id: state.todos.length + 1
});
return Object.assign({}, state, {
    todos: state.todos.concat(Object.assign({}, newTodo)),
    lastUpdate: new Date()
})

在您的原始代码中,您基本上是在改变从动作传入的待办事项。

于 2019-05-15T13:26:05.693 回答