函数式 JavaScript(一)简介
让我们假装现在要完成一个任务:尽可能按照函数式语言的原则来写JavaScript代码。
接下来一系列文章就是为了让你们和我一起开始这样一段旅程。首先,我们需要纠正一些你们脑子中可能有的对函数式语言错误的概念。
JS语言中的函数式被严重误解。
很显然,有相当多的开发者要每天用JavaScript的函数式范式 。我想说有更大一部分JavaScript 开发者没有真正理解这些东西。
我认为造成这个的原因是绝大多数用于Web服务器端的开发语言都是来源于C,而大家都知道这些语言不是函数式语言。
一般有两个层面的困惑。第一层是关于以下示例中的用法,这是jQuery中非常常见的用法:
$(".signup").click(function(event){ $("#signupModal").show(); event.preventDefault(); });
在上面这段代码中:我们传了一个匿名函数作为参数,这就是在JavaScript 中臭名昭著的回调函数。这些函数会被调用吗?根本不会!
上面这个例子说明了函数式语言的一个关键特征:函数是一种参数。另一方面,这个例子只用三行代码违反了几乎所有能违反的函数式编程范式。
第二层的疑惑是更微妙的。看看这个:只有少数时髦的JS开发者是这样看自己的:
嗯,真不错!但是我已经完全了解函数式编程,我在所有的项目中都用了Underscore.js。
Underscore.js是一个非常著名并且随处可见的JavaScript 库。举个例子:假设我有一组词,并且我需要每个词对应的前两个字母。这用Underscore.js来写非常简单:
var firstTwoLetters = function(words){ return _.map(words,function(word){ return _.first(word,2); }); };
看这个JavaScript 例子。我用了函数式中精致又实用的函数:_.map和_.first。对于这个大家有什么想法?
虽然underscore.js和 _.map这样的函数都是很有用的函数式范式,但是像这个例子中这样把这些东西放在一起还是让我感到有些难以理解。我们真的需要这样做吗?
如果我们开始思考怎样才能更加“函数式”,也许我们可以把上面的例子改写成这样:
// ...a little bit of magic var firstTwoLetters = map(first(2));
仔细想想,这一行代码和上面的5行是一样的效果。很多词只是参数或占位符。真正的逻辑在于把map函数、first函数和常量2用有意义的方式组合在一起。
有些人可能在想:这个例子中的神奇之处在哪里?毕竟,说任何一个例子神奇都有点像吹嘘,对吧?
我正打算用接下来的两篇文章来解释上面这个例子到底神奇在哪,如果你好奇的话,可以继续往下看。
这一系列博客是为了帮助大家怎样把函数式编程的美妙之处应用到你的JavaScript代码中。
下一节中,我将讨论JavaScript 语言中函数式及非函数式的多种元素。有了这些知识,我们可以通过把这些元素整合在一起,慢慢的在脑中形成函数式编程的完整体系,并且理解它们在JavaScript中的表现。