聊聊 Pure Function

定义

Pure Function 是不依赖且不改变其外部作用域中变量的函数
A pure function doesn’t depend on and doesn’t modify the states of variables out of its scope.

Pure Function 是 Functional Programming 的核心

稍微有点抽象,别急…

不依赖 & 改变外部作用域变量的值

看下面这个 function

1
2
3
4
5
6
7
8
9
10
11
12
13
var values = { a: 1 };

function impureFunction(items) {
var b = 1;

items.a = items.a * b + 2;

return items.a;
}

var c = impureFunction(values);

console.log(values, c); // {a: 3}, 3

这个 function 依赖了其外部作用域中的变量,并且把外部作用域变量中的属性值改了,这个 function 不是干净的 function,它容易产生副作用(side effect)

使用 Pure Function 改写

1
2
3
4
5
6
7
8
9
10
11
12
13
var values = { a: 1 };

function impureFunction(a) {
var b = 1;

a = a * b + 2;

return a;
}

var c = impureFunction(values.a);

console.log(values, c); // {a: 1}, 3

这时候函数并没有改变 values 对象的 a 属性值,它是一个 Pure Function

再来看一个常见的需求,求以下对象数组中所有 price 总和

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
const expenses = [
{
name: 'Rent',
price: 500,
type: 'Household'
}, {
name: 'Netflix',
price: 5.99,
type: 'Services'
}, {
name: 'Gym',
price: 15,
type: 'Health'
}, {
name: 'Bills',
price: 100,
type: 'Household'
}
];

传统方式

1
2
3
4
5
6
7
8
9
var total = 0;

//other code goes here

for(var i=0; i<expenses.length; i++) {
total += expenses[i].price;
}

console.log(total);

很明显结果不会错,但是这中写法的缺陷:

  • 它依赖外部作用域中的变量 total,而这个变量有可能在其他代码中被覆盖,很难去追踪它的状态变化,不好预测
  • 如果有另一个需求也是求所用数组的属性和,那这个 for 循环又得写一遍

使用 Pure Function

1
2
3
4
5
6
7
function sum(arr) {
return arr.reduce(function(total, item) {
return total += item.price;
}, 0);
}

console.log(sum(expenses));

好处一目了然

Views

Pure Function 特征:

  1. 必须有返回值
  2. Same Input,Same Output

使用 Pure Function 的好处

  • 没有副作用,因为它不会改变它外部作用域中变量的状态
  • 容易单元测试,因为 Pure Function 不依赖外部作用域的变量,只需要关心输入和输出值
  • 使代码更佳简洁,更灵活,提高复用性

Pure Function in javascript