这不是纯粹的功能吗?

时间:2019-05-15 13:07:03

标签: javascript redux state pure-function

我正在学习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;
}

2 个答案:

答案 0 :(得分:2)

TL; DR-不,不是。

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

  

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

     
      
  1. 对于相同的参数,其返回值相同(   局部静态变量,非局部变量,可变引用   参数或来自I / O设备的输入流)。

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

  4.   

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

您遇到这种情况的原因是,每个函数调用的日期都不同-不管传递的参数如何。

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

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

答案 1 :(得分: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()
})

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