纯函数遵循三个主要原则:
该函数具有单一职责
该函数应该只做一件事。
该功能没有副作用
该函数不会在其范围之外更改状态。
该函数是引用透明的
该函数对于相同的输入输出相同的值。
下一步是探索这些原则对功能设计的影响。
你的函数已经满足了第一个原则,尽管名称应该改进;)
它也满足第二个原则,因为它不会修改其范围(其输入参数)之外的任何其他内容。
不幸的是它不符合第三条原则:
var a = {
a : 1,
b : 2
};
var b = transformObject(a);//b = {2, 4}
var c = transformObject(a);//c = {4, 8}
相同的输入(a
)但输出不同。这就违反了第三条原则。
引用透明的函数需要不可变的数据。
一个很好的答案已经发布了尼娜·肖尔茨:
function transformObject(a) {
var b = {};
Object.keys(a).forEach(function (k) { b[k] = a[k] * 2; });
return b;
}
但它仅在输入对象不包含嵌套在其中的任何其他对象时才起作用。
现在有一些很好的库可以为您提供不可变的结构(例如不可变JS).
使用 ImmutableJS 的简单示例:
describe('a List', () => {
function addMovie(currentState, movie) {
return currentState.push(movie);
}
it('is immutable', () => {
let state = List.of('Avengers', 'Antman');
let nextState = addMovie(state, 'Superman');
expect(nextState).to.equal(List.of(
'Avengers',
'Antman',
'Superman'
));
expect(state).to.equal(List.of(
'Avengers',
'Antman'
));
});
it('can be updated and returns another immutable List', () => {
let state = List.of(1,2,3,4);
let nextState = state.map(value => value*2);
expect(nextState).to.equal(List.of(2,4,6,8));
expect(state).to.equal(List.of(1,2,3,4));
});
});
您可以阅读有关不可变 API 的更多信息here