作家
登录

JavaScript的函数式编程,你了解吗?

作者: 来源: 2017-10-26 09:46:30 阅读 我要评论

递归计算 3! 的客栈(三次乘法)

你可能会想象当计算 n = 20000 时客栈会更高。我们可以做些什么竽暌古化它吗?当然可以。作为 ES2015 (别名 ES6) 标准的一部分,有一个优化用来解决这个问题。它被称作尾调用优化proper tail calls optimization(PTC)。当递归函数做的最后一件事是调用本身并返回结不雅的时刻,它使得浏览器删除或者忽视客栈帧。实际上,这个优化对于互相递归函数也是有效的,然则为了简单起见,我们照样来看单一递归函数。

  1. 'use strict'
  2. // Optimized for tail call optimization. 
  3. function factorial(n, product = 1) { 
  4.   if (n === 0) { 
  5.     return product; 
  6.   } 
  7.   return factorial(n - 1, product * n) 

让我们来看看竽暌古化后的计算 factorial(3) 时的客栈。如下图所示,客栈不会增长到跨越两层。原因是我们把须要的信息都传到了递归函数中(比如 product)。所以,在 product 被更新后,浏览器可以丢弃掉落客栈中本来的帧。你可以在图中看到每次最膳绫擎的帧下沉变成了底部的帧,本来底部的帧被丢弃,因为不再须要它了。

递归计算 3! 的客栈(三次乘法)应用 PTC

如今选一个浏览器运行吧,假设你在应用 Safari,你会获得 Infinity(它是比在 JavaScript 中能表达的最大年夜值更大年夜的数)。然则我们没有获得客栈溢掉足误,那很不错!如今在其他的浏览器中呢怎么样呢?Safari 可能如今甚至将来是实现 PTC 的独一一个浏览器。看看下面的兼容性表格:

PTC 兼容性

其他浏览器提出了一种被称作语法级尾调用syntactic tail calls(STC)的竞争标准。“语法级”意味着你须要用新的语法来标识你想要履行尾递归优化的函数。即使浏览器还没有广泛支撑,然则把你的递归函数写成支撑尾递归优化的样子照样一个好主意。

高阶函数

我们已经知道 JavaScript 将函数视作一等公平易近,可以把函数像其他值一样传递。所以,把一个函数传给另一个函数也很常见。我们也可以让函数返回一个函数。就是它!我们有高阶函数。你可能已经很熟悉几个在 Array.prototype 中的高阶函数。比如 filter、map 和 reduce 就在个中。对高阶函数的一种懂得是:它是接收(一般会调用)一个回调函数参数的函数。让我们来看看一些内置的高阶函数的例子:

留意我们在一个数组对象上调用其办法,这是面向对象编程的特点。如不雅我们想要更函数式一些,我们可以用 Rmmda 或者 lodash/fp 供给的函数。留意如不雅我们应用 R.compose 的话,须要倒转函数的次序,因为它大年夜右向左依次调用函数(大年夜底向上);然而,如不雅我们想大年夜左向右调用函数就像膳绫擎的例子,我们可以用 R.pipe。下面两个例子用了 Rmmda。留意 Rmmda 有一个 mean 函数用来代替 reduce 。

关于函数组合的几个要点:

  1. 我们可以组合随便率性数量的函数(不仅限于 2 个)。
  2. 组合函数的一个方法是简单地把一个函数的输出作为下一?函数的输入(比如 f(g(x)))。

应用函数式办法的长处是清跋扈地分开了数据(vehicles)和逻辑(函数 filter,map 和 reduce)。面向对象的代码比拟之下把数据和函数用以办法的对象的情势混淆在了一路。

不规范地说,柯里化currying是把一个接收 n 个参数的函数变成 n 个每个接收单个参数的函数的过程。函数的 arity 是它接收参数的个数。接收一个参数的函数是 unary,两个的是 binary,三个的是 ternary,n 个的是 n-ary。那么,我们可以把柯里化定义成将一个 n-ary 函数转换成 n 个 unary 函数的过程。让我们经由过程简单的例子开端,一个计算两个向量点积的函数。回想一下线性代数,两个向量 [a, b, c] 和 [x, y, z] 的点积是 ax + by + cz。

  1. function dot(vector1, vector2) { 
  2.   return vector1.reduce((sum, element, index) => sum += element * vector2[index], 0); 
  3. const v1 = [1, 3, -5]; 
  4. const v2 = [4, -2, -1]; 
  5. console.log(dot(v1, v2)); // 1(4) + 3(-2) + (-5)(-1) = 4 - 6 + 5 = 3 

      推荐阅读

      如何处理JavaScript内存泄露

    沙龙晃荡 | 去哪儿、陌陌、ThoughtWorks在主动化运维中的实践!10.28不见不散! 几周前,我们开端写一个系列,>>>详细阅读


    本文标题:JavaScript的函数式编程,你了解吗?

    地址:http://www.17bianji.com/lsqh/38230.html

关键词: 探索发现

乐购科技部分新闻及文章转载自互联网,供读者交流和学习,若有涉及作者版权等问题请及时与我们联系,以便更正、删除或按规定办理。感谢所有提供资讯的网站,欢迎各类媒体与乐购科技进行文章共享合作。

网友点评
自媒体专栏

评论

热度

精彩导读
栏目ID=71的表不存在(操作类型=0)