blackLearning.github.io
blackLearning.github.io copied to clipboard
JS函数式编程指南
JS函数式编程指南
一些通用的编程指南原则
- DRY(不要重复自己,don't repeat yourself),
- YAGNI (你不会用到它的,ya ain't gonna need it),
- Rule Of Three原则 (当重复的次数超过3次,就应该考虑抽象封装)
- 高内聚低耦合(loose coupling high cohesion),
- 最小意外原则(Principle of least surprise),
- 单一责任(single responsibility)
遵循开闭原则设计出的模块具有两个主要特征: (1)对于扩展是开放的(Open for extension)。这意味着模块的行为是可以扩展的。当应用的需求改变时,我们可以对模块进行扩展,使其具有满足那些改变的新行为。也就是说,我们可以改变模块的功能。 (2)对于修改是关闭的(Closed for modification)。对模块行为进行扩展时,不必改动模块的源代码或者二进制代码。模块的二进制可执行版本,无论是可链接的库、DLL或者.EXE文件,都无需改动。
纯函数的好处
纯函数是这样一种函数,即相同的输入,永远会得到相同的输出,而且没有任何可观察的副作用。
概括来讲,只要是跟函数外部环境发生的交互就都是副作用——这一点可能会让你怀疑无副作用编程的可行性。函数式编程的哲学就是假定副作用是造成不正当行为的主要原因。
从定义上来说,纯函数必须要能够根据相同的输入返回相同的输出;如果函数需要跟外部事物打交道,那么就无法保证这一点了。
纯函数没有副作用,一些你要记住的是,它不会:
- 访问函数以外的系统状态
- 修改以参数形式传递过来的对象
- 发起http请求
- 保留用户输入
- 查询DOM
可缓存性
首先,纯函数总能够根据输入来做缓存。
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];
};
};
纯函数的依赖很明确,因此更易于观察和理解——没有偷偷摸摸的小动作。
可测试性
纯函数让测试更加容易。
我们不需要伪造一个“真实的”支付网关,或者每一次测试之前都要配置、之后都要断言状态(assert the state)。
curry(柯里化)
我在上面的代码中遵循的是一种简单,同时也非常重要的模式。即策略性地把要操作的数据(String, Array)放到最后一个参数里。
compose(代码组合)
pointfree 模式指的是,不要命名转瞬即逝的中间变量, 永远不必说出你的数据。它的意思是说,函数无须提及将要操作的数据是什么样的。一等公民的函数、柯里化(curry)以及组合协作起来非常有助于实现这种模式。
// 非 pointfree,因为提到了数据:word
var snakeCase = function (word) {
return word.toLowerCase().replace(/\s+/ig, '_');
};
// pointfree
var snakeCase = compose(replace(/\s+/ig, '_'), toLowerCase);
声明式代码
// 命令式
var makes = [];
for (i = 0; i < cars.length; i++) {
makes.push(cars[i].make);
}
// 声明式
var makes = cars.map(function(car){ return car.make; });
总结:『函数对于外部状态的依赖是造成系统复杂性大大提高的主要原因』 『让函数尽可能地纯净』