Разве это не чистая функция? - PullRequest
0 голосов
/ 15 мая 2019

Я изучаю управление состоянием для веб-разработки, и наткнулся на это учебное пособие по редуксу с простой функцией, как показано ниже.Однако утверждение: "action.todo.id = state.todos.length + 1;"заставляет меня подозревать, что эта чистая функция была ... IMPURE.Пожалуйста, просветите меня, спасибо!

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 ]

2 голосов
/ 15 мая 2019

TL; DR - нет, это не так.

Давайте рассмотрим определение чистой функции.Из википедии:

В компьютерном программировании чистая функция - это функция, имеющая следующие свойства:

  1. Ее возвращаемое значение одинаково для тех же аргументов(без изменений с локальными статическими переменными, нелокальными переменными, изменяемыми ссылочными аргументами или входными потоками с устройств ввода-вывода).

  2. Его оценка не имеет побочных эффектов (нет мутации локальных статических переменных, нелокальных переменных, изменяемых ссылочных аргументов или потоков ввода-вывода).

Хотя ваша функция соответствует второму условию, использование new Date() - делает ее нечистой.

Причиной ее нечистоты в вашем случае является тот факт, что дата отличается для каждого извызов функций - независимо от переданных параметров.

Для того, чтобы сделать его чистым, вы должны передать дату в качестве дополнительного параметра, который позволит вам иметь одинаковые выходные данные для одного и того же ввода.

Zaptree также упомянул, что изменение длины идентификаторов вашего предмета, то есть action.todo.id = state.todos.length + 1, является нечистым, поскольку это может повлиять на другие стороны, ссылающиеся на него.

0 голосов
/ 15 мая 2019

Вы очень правильно поняли, что следующий код нечист:

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()
})

В исходном коде вы, по сути, изменяете задачу, переданную от действия.

...