JavaScript函数式编程之为何要函数式编程(非严谨技术层面的扯淡)

个人github github.com/zhuanyongxi…javascript

这多是一篇会被常常改动的文章,它记录了如今的我对函数式编程粗浅的理解。html

函数式编程并非github上面的一个工具库,它的年龄比JavaScript要大得多,它是一种通过了几十年,被众多计算机科学家证实了的行之有效的编程范式。它不是学会了几个函数式编程工具的API就能彻底掌握的,它更多的是编程思惟上的转变。具体一点的代码实例能够看《JavaScript函数式编程之pointfree与声明式编程》java

那到底为何用使用函数式编程git

若是总结成一个字,那就是为了“爽”。“爽”在哪?读和写github

这可能会让你不觉得然,读和写对你来讲可能不是最重要的事情。不过以我当前的认知水平来看,设计模式、编程范式,甚至是编程语言自己,他们的最大意义都在于这两个字。编程

代码是给人看的

好比编程语言,它的落点在于“语言”,“语言”是用来干什么的?交流沟通。跟谁交流沟通?跟人,而非机器。咱们写的代码会通过层层编译,最终转化成0和1才能被计算机执行。那咱们为何要这么麻烦,而不直接用0和1编程?由于很差写也很差读。若是你手速足够快,大脑也足够发达,用0和1编程也是能够的。可那样的话,还须要计算机吗?虽然层层编译的过程,势必会下降效率,不过有摩尔定律来接盘,大可没必要担忧。设计模式

函数式的“好读”体如今哪里?

若是所有功能的实现只须要几行代码,大谈设计模式、编程范式就太矫情了。咱们之因此须要这些东西,是由于随着代码量的增多,代码的读写对咱们形成了困扰。数组

那函数式编程是如何解决这些问题的?编程语言

好比纯函数,它有不少优势,我的认为最重要的是:它明显的下降咱们的认知负荷。ide

从最普通的函数提及:

var a = 1;
function A(val) {
  a = 2;
  return a + val;
} 
复制代码

这里的变量a就是被你们嗤之以鼻的全局变量。它很是容易致使出现bug,当代码量不少的时候,极可能会由于重名而被覆盖,从而致使其余使用了这个变量的程序出错。即使是正常的修改,当咱们再次使用函数A的时候,弄清变量a当前的状态也是十分的困难,这就使得函数A变得难以理解,难以理解的函数就得不到使用者的信任

面向对象编程的“封装”在必定程度上解决了这个问题:

var obj = {
  a: 1,
  A: function(val) {
    return this.a + val;
  }
}
复制代码

封装了以后全局变量大大的减小了,即使有两个对象重名了,相对上面的状况,修改起来也不会有那么大的负担。但它并无完全解决这一问题,由于属性a是可变的,每次调用方法A的时候,弄清属性a的状态依然不容易。

而函数式编程不存在这个问题。在函数式编程中,使用可变的外部的变量是不被容许的。例如:

var a = 1;	// 除了当作参数传入,使用变量a的函数都不是纯函数
function A(val) {	// 不是纯函数
  return a + val;
}


const b = 1;
const B = function(val) {	// 纯函数
  return b + val;
}
复制代码

随着代码量逐渐增多,这种写法的优点就愈发明显了,若是还能更进一步的减小耦合,那你就能够在很大程度上去“断章取义”,不去管上下文。每个纯函数咱们均可以充分信任,它的输出只与传进去的参数有关。

不只仅在函数式编程中,面向对象的编程一般也会建议写纯函数。

纯函数对代码的调试也有极大的好处,这也是函数式编程的优势之一:方便调试。

在初学函数式编程的时候,会很难理解这一点,由于当咱们使用纯函数帮咱们解决问题的时候,老是得不到想要的结果,尤为是在使用函数式的工具库进行函数组合的时候,断点调试都很困难,就算你把断点打到了第三方的工具库里面,你真的肯定你能在短期内看懂人家的源码吗?这个时候每每只能想办法去console.log。不过这个问题是能够经过不断的学习总结来解决的。即使使用其余的方式编程,不熟悉所用的工具也会出现一样的状况,这并非函数式编程的问题。

绝大多数的bug都是由反作用引发的。也就是系统状态的变化。这一点没法经过学习来解决,你能记住成千上万个状态,并能时刻了解他们的变化吗?可若是咱们是在函数式编程,使用了大量的纯函数,因为纯函数不产生反作用,在调试的时候,咱们只须要去调试会产生反作用的部分就能够了。

在函数式编程中,一切的技巧的目的都是为了让你的代码更加的函数式。可掌握有些技巧的成本很高,这就致使部分人对函数式编程的”可读性“产生了质疑。

其实,函数式代码的可读性与读代码的人的函数式编程的能力有直接的关系。以下图:

命令式编程很符合人类的思惟习惯,入门的成本很低,而声明式的函数式编程的学习则有必定的门槛,对于新手来讲,可能几乎没有可读性。只有不断的深刻学习,这种可读性的优点才会逐渐的体现出来。这多是致使函数式编程没有被普遍应用的最主要缘由。

函数式编程的一些问题

  1. 可读性的疑惑。pointfree的声明式的写法有时候很难讲究竟是提升了可读性仍是下降了可读性,特别是在你没有在函数的命名上很好的体现出这个函数的功能、参数和返回值的详细信息的状况下(能提现出来吗?)。真正的函数式编程语言有类型签名,固然你能够用这种方式给你的函数加上注释。但是,熟练掌握类型签名也不是一件容易的事情。
  2. 用的人太少。多是入门门槛的问题,如今大多数的编程仍是面向对象的。若是仅仅是用一个函数式的工具库帮助处理一下数据可能不是大问题。可若是你把各类进阶的技巧如函子、范畴学的公式等在实际项目中用的不亦乐乎,你的不太熟悉函数式编程的同事可能会骂街。
  3. 函数式编程一般会大量的使用柯里化,理论上会影响性能,进而影响体验。可因为运行环境种类太多,这一点很差量化,要根据具体的状况讨论。
  4. 习惯了命令式编程,转变成函数式编程会有点困难。你的面向对象用的越好,可能转起来就越困难。我(我面向对象用的很差)目前在用函数式编程时,不少时候都是先用命令式的方式想清楚,再改为函数式。在脑壳里面装一个编译器,十分费电。

若是还要举的话。。。

  1. 代码量很大的时候,声明式的编程,给函数起名字会很辛苦。。。。。。。吧?

函数式编程与面向对象编程

面向对象编程更倾向于封装,而函数式编程更倾向于抽象。

面向对象编程抽象的结果是一个类,函数式编程抽象的结果是一个过程(一个函数)。

封装和抽象有什么区别?

他们并无明显的界限,抽象是经过封装来实现的,我找不到一个只是抽象而不是封装的例子。封装和抽象的目的略有不一样。简单的讲,封装只是把一些会再次使用的操做包起来,等待下次使用。抽象也会有“包起来”的动做,可它更多的目的在于要划清界限。这就比如让咱们解释一个概念,若是你说“我懂,但我就是说不出来”,那么大几率你是没有懂。咱们是否能清晰准确的说清楚,取决于咱们脑中对这一律念的界限是否划清楚了。若是没有划清楚,咱们就没办法下断语去说明它是什么和它不是什么。抽象也是如此,它须要咱们搞清楚它是干什么的,把不该该干的事情都去掉。“它是什么”这一点越明确,那么这一封装的抽象程度就越高。

参考资料:

相关文章
相关标签/搜索