我正在尝试确定编写可以执行多个动作的函数时的最佳实践。我当前的解决方案是使用一个字符串参数来告诉函数该做什么(例如,updateTasks('complete selected', data);
)。
我意识到我可以将此功能拆分为多个功能,但是我会以这种方式重复很多次。我的另一种选择是以布尔语句的形式使用更多参数,但我读到了use fewer arguments。
let data = {
selectedTasks:[1,3],
tasks: [
{
id: 1,
title: 'get milk',
complete: false,
},
{
id: 2,
title: 'feed cat',
complete: true,
},
{
id: 3,
title: 'exercise',
complete: false,
}
]
};
根据lealceldeiro的建议进行了更新
updateTasks = (action, data) => {
const taskChanges = data.tasks.map(task => {
const isSelected = data.selectedTasks.indexOf(task.id) > -1;
if ((action === 'complete selected' && isSelected) ||
(action === 'complete nonselected' && !isSelected) ||
(action === 'complete all'))
return Object.assign({}, task, {complete: true});
if ((action === 'uncomplete selected' && isSelected) ||
(action === 'uncomplete nonselected' && !isSelected) ||
(action === 'uncomplete all'))
return Object.assign({}, task, {complete: false});
return task; // keep as is
});
return taskChanges;
};
updateTasks('complete selected', data);
这是最佳实践,还是最好将功能拆分?我希望我的代码尽可能干燥且清晰易读。
答案 0 :(得分:1)
我不知道有任何反模式。实际上有一个command pattern。但是,与其传递一个字符串,不如传递一个函数以返回完整状态。
const completeAllAction = () => true; //prev, isSelected parms ignored
const uncompleteAllAction = () => false;
const compleSelectedAction = (prev, isSelected ) => isSelected ? true : prev;
const compleNonSelectedAction = (prev, isSelected ) => !isSelected ? true : prev;
const uncompleSelectedAction = (prev, isSelected ) => isSelected ? false : prev;
const uncompleNonSelectedAction = (prev, isSelected ) => !isSelected ? false : prev;
const updateTasks = (action, data) => {
const taskChanges = data.tasks.map(task => {
const isSelected = data.selectedTasks.indexOf(task.id) > -1;
const newComplete = action(task.complete, isSelected);
return Object.assign({}, task, {complete: newComplete});
});
return taskChanges;
};
updateTasks(completeAllAction, data);
我强烈建议您不要在if语句后省略{bloc}。有关详细信息,请参见Crockford的JavaScript the good parts。
您还可以使用function composition来减少参数数量并保持代码干燥。
const getUpdateTasksFunction = action => {
//return a function that takes the data object
return (data) => {
return data.tasks.map(task => {
const isSelected = data.selectedTasks.indexOf(task.id) > -1;
const newComplete = action(task.complete, isSelected);
return Object.assign({}, task, {complete: newComplete});
});
}
}
const uncompleteAll = getUpdateTasksFunction(uncompleteAllAction);
const compleNonSelected = getUpdateTasksFunction(compleNonSelectedAction);
// ... continue for each action
//usage with only one param
const newData = uncompleteAll(data);