DRY(不要重复本身,don't repeat yourself)web
高内聚低耦合(loose coupling high cohesion)数据库
YAGNI (你不会用到它的,ya ain't gonna need it)编程
最小意外原则(Principle of least surprise)浏览器
单一责任(single responsibility)等等。缓存
var xs = [1,2,3,4,5];
// 纯的
xs.slice(0,3);
//=> [1,2,3]
xs.slice(0,3);
//=> [1,2,3]
xs.slice(0,3);
//=> [1,2,3]
// 不纯的
xs.splice(0,3);
//=> [1,2,3]
xs.splice(0,3);
//=> [4,5]
xs.splice(0,3);
//=> []
复制代码
silce 就是一个纯函数,没有改变初始的值。而咱们经常使用的 splice 就是一个影响初始值的不纯的函数。app
反作用可能包括如下,但不限于:函数式编程
更改文件系统 往数据库插入记录 发送一个 http 请求 可变数据 打印/log 获取用户输入 DOM 查询 访问系统状态 函数
咱们能够归纳来看,只要和外部环境发生必定交互的都是反作用。咱们在书写纯函数的时候尽可能要保持无反作用的交互。post
固然并非要禁止一切的反作用,而是说咱们须要在可控的范围内去发生。学习
咱们在初中开始学习函数的时候知道:函数是不一样数值之间的特殊关系:每个输入值返回且只返回一个输出值。
下面来实现一个缓存的函数
var squareNumber = memoize(function(x){ return x*x; });
squareNumber(4);
//=> 16
squareNumber(4); // 从缓存中读取输入值为 4 的结果
//=> 16
squareNumber(5);
//=> 25
squareNumber(5); // 从缓存中读取输入值为 5 的结果
//=> 25
复制代码
这里看看 memoize 缓存函数是怎么实现的
var memoize = function(f) {
var cache = {};
return function() {
var arg_str = JSON.stringify(arguments);
cache[arg_str] = cache[arg_str] || f.apply(f, arguments);
return cache[arg_str];
};
};
复制代码
下面会看到这种缓存函数的实用性
纯函数是彻底自给自足的,它须要的全部东西都能轻易得到。仔细思考思考这一点...这种自给自足的好处是什么呢?首先,纯函数的依赖很明确,所以更易于观察和理解
最后一点,也是决定性的一点:咱们能够并行运行任意纯函数。由于纯函数根本不须要访问共享的内存,并且根据其定义,纯函数也不会因反作用而进入竞争态(race condition)。
并行代码在服务端 js 环境以及使用了 web worker 的浏览器那里是很是容易实现的,由于它们使用了线程(thread)。不过出于对非纯函数复杂度的考虑,当前主流观点仍是避免使用这种并行。
运用以上的规则,来合理的使用纯函数式的编程,这样咱们的代码会更加的优雅。