js--函数式编程中的纯函数与副作用

一、纯函数

纯函数是这样一种函数,即相同的输入,永远会得到相同的输出,而且没有任何可观察的副作用。

举例1:数组的两个方法:slice与splice。

这两个函数的作用并无二致——但是注意,它们各自的方式却大不相同,但不管怎么说作用还是一样的。我们说 slice 符合纯函数的定义是因为对相同的输入它保证能返回相同的输出。而 splice 却会嚼烂调用它的那个数组,然后再吐出来;这就会产生可观察到的副作用,即这个数组永久地改变了。

var	xs = [1,2,3,4,5];
var	xp = [1,2,3,4,5];
//纯的
xs.slice(0,3); //=>[1,2,3]
xs.slice(0,3); //=>[1,2,3]
xs.slice(0,3); //=>[1,2,3]
console.log(xs); //=>[1,2,3,4,5];

//不纯的
xp.splice(0,3); //=>[1,2,3]
xp.splice(0,3); //=>[4,5]
xp.splice(0,3); //=>[]
console.log(xp); //=>[];

在函数式编程中,我们讨厌这种会改变数据的笨函数。我们追求的是那种可靠的,每次都能返回同样结果的函数,而不是像 splice这样每次调用后都把数据弄得一团糟的函数,这不是我们想要的。

举例2:

//不纯的
var	minimum	= 21;
var	checkAge = function (age)	{
	return age >= minimum;
};

//纯的
var	checkAge = function (age)	{
	var	minimum	= 21;
	return age >= minimum;
};

在不纯的版本中,checkAge的结果将取决于minimum这个可变变量的值。换句话说,全局作用域下的minimum改变之后,会影响checkAge的结果。在纯的版本中,minimum值被限定在函数作用域中,外部无法直接修改,所以函数结果只会和参数age有关。

二、副作用

副作用是在计算结果的过程中,系统状态的一种变化,或者与外部世界进行的可观察的交互。

“作用”我们可以理解为一切除结果计算之外发生的事情。
“副作用”的关键部分在于“副”。就像一潭死水中的“水”本身并不是幼虫的培养器,“死”才是生成虫群的原因。同理,副作用中的“副”是滋生bug的温床。

概括来讲,只要是跟函数外部环境发生的交互就都是副作用——这一点可能会让你怀疑无副作用编程的可行性。函数式编程的哲学就是假定副作用是造成不正当行为的主要原因。

这并不是说,要禁止使用一切副作用,而是说,要让它们在可控的范围内发生。副作用让一个函数变得不纯是有道理的:从定义上来说,纯函数必须要能够根据相同的输入返回相同的输出;如果函数需要跟外部事物打交道,那么就无法保证这一点了。

参考书籍:函数式编程

发布了45 篇原创文章 · 获赞 7 · 访问量 1万+

猜你喜欢

转载自blog.csdn.net/ThisEqualThis/article/details/103408306
今日推荐