函数十分强大。
但我们要清楚什么是函数。它不只是一个语句/操作的集合。具体地说,一个函数需要一个或多个输入(理想情况,只有一个!)以及一个输出。
函数内部的函数可以拥有外部变量的闭包,为稍后的访问记住它们。这是所有种类的编程中最重要的概念之一,而且是 FP 基础中的基础。
要小心匿名函数,特别是箭头函数 =>。它们写起来方便,但是将作者的成本转嫁到了读者身上。我们学习 FP 的所有原因就是写出可读性更强的代码,所以先不要那么快就赶这个潮流。
不要使用 this 敏感的函数。别这么干。
现在我们在思想中对 函数 在函数式编程中意味着什么发展出了清晰而多彩的观点。是时候搬弄函数以使它们协作的时候了.
万法归一
一对一
说到仅含一个参数的函数,在 FP 工具箱中有另一个基本工具:一个函数,它接收一个实际参数但不作任何事情并原封不动地返回实际参数的值:
function identity(v) {
return v;
}
// 或者 ES6 => 箭头形式
var identity =
v =>
v;
这个工具看起来如此简单,以至于很难有什么用处。但即使是简单的函数也可以在 FP 的世界中很有用处。就像人们关于表演所说的:剧中没有小角色,只有小演员。
例如,想象你想使用一个正则表达式分割一个字符串,但是结果数组中可能含有一些空值。要去掉这些空值,我们可以使用 JS 的 filter(..)
数组操作
var words = " Now is the time for all... ".split( /\s|\b/ );
words;
// ["","Now","is","the","time","for","all","...",""]
words.filter( identity );
// ["Now","is","the","time","for","all","..."]
因为 identity(..)
简单地返回传递给它的值,JS 会将每个值强制转换为 true
或 false
,并以此决定每个值是保留还是排除出最终的数组。
使用identity(..)
的另一个例子是在变形的地方作为默认函数:
function output(msg,formatFn = identity) {
msg = formatFn( msg );
console.log( msg );
}
function upper(txt) {
return txt.toUpperCase();
}
output( "Hello World", upper ); // HELLO WORLD
output( "Hello World" ); // Hello World
一个不变的值
特定的 API 不允许你将一个值直接传入一个方法,但要求你传入一个函数,即使这个函数只是返回这个值。一个这样的 API 就是 JS Promise 的 then(..)
方法:
// 不能工作:
p1.then( foo ).then( p2 ).then( bar );
// 而是:
p1.then( foo ).then( function(){ return p2; } ).then( bar );
许多人声称 ES6 =>
箭头函数就是 “解决方案”:
p1.then( foo ).then( () => p2 ).then( bar );
但是有更合适的
function constant(v) {
return function value(){
return v;
};
}
// 或者 ES6 => 箭头形式
var constant =
v =>
() =>
v;
使用这个小小的工具,我们可以解决 then(..)
的烦恼:
p1.then( foo ).then( constant( p2 ) ).then( bar );
网友评论