blackLearning.github.io icon indicating copy to clipboard operation
blackLearning.github.io copied to clipboard

JS函数式编程指南

Open Fadingvision opened this issue 7 years ago • 0 comments

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; });

总结:『函数对于外部状态的依赖是造成系统复杂性大大提高的主要原因』   『让函数尽可能地纯净』

Fadingvision avatar Aug 14 '17 16:08 Fadingvision