怎么理解函数是一等公民
可以像对待其他任何数据类型一样对待函数,比如可以把函数当做参数传递、赋给变量等等。所以用一个函数把另外一个函数包起来的写法没有必要。
const hi = name => `Hi ${name}`; const greeting = name => hi(name); greeting("Mary");
因为可以直接把函数赋给另一个变量。上面的写法等同于
const hi = name => `Hi ${name}`; const greeting = hi; greeting("Mary");
纯函数
纯函数的概念:相同的输入,永远得到相同的输出,而且没有任何可观察的副作用。
什么是副作用:一切除结果计算之外发生的事情。只要是跟函数外部环境发生的交互就都是副作用
理解纯函数的好处
并行代码(最重要的好处)
并行代码可以在服务端js环境和web worker浏览器中实现。可以并行运行纯函数的原因是:
- 纯函数不需要访问共享的内存
- 纯函数不会因为副作用进入竞争态(纯函数没有可观察的副作用)
可缓存性
概念:纯函数能根据输入来做缓存。
这句话的意思应该是纯函数能被用来做缓存,因为纯函数具有相同输入,永远得到相同输出的特性。
比如书上这个例子,memorize这个函数对传入的纯函数f每次的结果进行了一个缓存。所以第二次调用squreNumber(4)时,直接从cache[4]中去找之前缓存的结果并返回,不需要再次计算。
因为传入的函数f是纯函数,memorize缓存函数才有意义,如果传入的函数f是一个不纯的函数(比如说一个random函数,相同的输出却产生不同的结果),那么memoize函数就失去意义了。因为在squreNumber函数中传入相同的值x,执行的时候仍旧每次从cache[x]中拿出第一次执行产生的缓存结果。但是实际我想要的是相同的输入参数x,要返回不同的随机数。参考链接:adispring.github.io/2017/12/04/…
通过延迟执行的方式把不纯的函数转换为纯函数
当时没有看懂书上这个例子的意思。memoize仍然是之前例子中的那个缓存函数,意思应该是这次传进来的函数(称它为函数A)之所以是纯函数,是因为在这个函数中又包了一层,不直接返回操作结果。书里面之前说到发送http请求是有副作用的,是不纯的,而这里调用pureHttpCall()的时候并不会真正的发送http请求,而是又返回了另一个函数(称它为函数B),当调用这个函数B时才真正发出http请求。函数A现在满足了相同输入永远是相同输出这个条件,所以函数A可以说它是一个纯函数了,它也具有了可缓存性。
可移植性/自文档化
概念:纯函数与环境无关,可以在任何地方运行它
这个的意思应该是在不同的地方运行纯函数,不用担心它的结果会不会变异,它是很可靠的。所以纯函数被序列化并通过socket发送,也可以在web worker中运行。另一方面,只需看纯函数的内部实现就能明确它的作用。
可测试性
用纯函数的话,测试很方便,因为不用考虑环境。只要简单给一个输入,然后看输出是否符合预期
合理性
如何理解引用透明性
概念:一段代码 可以替换成它执行所得的结果,而且是在不改变整个程序性为的前提下替换的。
引用透明的意思就是如果把12行的isSameTeam(player, target)这句话直接替换成isSameTeam这个函数的返回结果player1.team === player2.team。这么做不会对这段程序的行为造成什么影响。所以说上面这段代码是引用透明的。