这不是纯函数吗?
Is this not a 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;
}
TL;DR - 不,不是。
让我们检查一下纯函数的定义。
来自维基百科:
In computer programming, a pure function is a function that has the
following properties:
Its return value is the same for the same arguments (no variation with
local static variables, non-local variables, mutable reference
arguments or input streams from I/O devices).
Its evaluation has no
side effects (no mutation of local static variables, non-local
variables, mutable reference arguments or I/O streams).
尽管您的函数确实符合第二个条件,但使用 new Date()
- 使其不纯。
您的情况不纯的原因是每个函数调用的日期都不同 - 无论传递的参数如何。
为了使其纯净,您应该将日期作为附加参数传递,这样您就可以对相同的输入获得相同的输出。
Zaptree 还提到改变项目 ID 的长度,即 action.todo.id = state.todos.length + 1
是不纯的,因为它可能会影响引用它的其他方。
您非常正确地意识到以下代码是不纯的:
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()
})
在您的原始代码中,您基本上改变了从操作传入的待办事项。
我正在学习 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;
}
TL;DR - 不,不是。
让我们检查一下纯函数的定义。 来自维基百科:
In computer programming, a pure function is a function that has the following properties:
Its return value is the same for the same arguments (no variation with local static variables, non-local variables, mutable reference arguments or input streams from I/O devices).
Its evaluation has no side effects (no mutation of local static variables, non-local variables, mutable reference arguments or I/O streams).
尽管您的函数确实符合第二个条件,但使用 new Date()
- 使其不纯。
您的情况不纯的原因是每个函数调用的日期都不同 - 无论传递的参数如何。
为了使其纯净,您应该将日期作为附加参数传递,这样您就可以对相同的输入获得相同的输出。
Zaptree 还提到改变项目 ID 的长度,即 action.todo.id = state.todos.length + 1
是不纯的,因为它可能会影响引用它的其他方。
您非常正确地意识到以下代码是不纯的:
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()
})
在您的原始代码中,您基本上改变了从操作传入的待办事项。