# 函数式编程入门(1)

函数式编程入门(1)

    因为es6的一些新特性,感觉是有点函数式编程的味道,所以也是了解了一波有关的东西吧,顺便记录下来,做个入门教程

(哪里有错的话还希望大家留言指正=-=)

什么是函数式编程,为什么要函数式?

    这个问题也许更应该去看什么知乎大佬之类的回答吧。我仅从自己看书包括写代码的理解来看,首先函数式是相对于命令式的吧。比如在es6之前,你要遍历一个数组的话,可能得像下面这样

	var arr = [1,2,3];
	for (var i = 0, length = arr.length; i < length; i++) {
		//	do something...
	}

    但是大家也都知道,在es6之中,我们可以这样

	var arr = [1, 2, 3];
	arr.forEach(el => {
		//	do something
	})

    简单的说这些也许并不能让你感受到函数式的魅力,但是想想,如果项目不断复杂,按照以往那样的命令式的写法,对于复杂结构甚至要好几层的for循环去拿索引,这对于后期维护来说是很操蛋的一件事情。哪怕是你自己写的代码,过几个月再来看一遍,也不得不跟着嵌套的for循环去捋逻辑,从而判断这代码究竟是想实现怎样的一个功能。而这些,实际上是可以通过封装一些简单易用的函数去实现的,通过良好的命名(比如es6filter),使得代码具有良好的可读性,我们可以仅仅通过看到函数的名字,就知道这里想干嘛,而不需要去过分关注具体的细节。而这仅仅是函数式带来的好处的一小部分,即良好的可读性易维护性。其他更多的好处我相信在后续的章节中大家会感受的比较深(如果不鸽的话#雾)

结束之前说一点更干的东西—闭包

    为什么说的是闭包呢?(当然是有用了,呸!),闭包的概念对于函数式而言我觉得是相当重要的吧,很多高阶函数的实现,都依赖闭包。下面一个很常见的代码(?也许不是那么常见)

	const cacheFn = (fn) => {
		const cache = {};	//	设置缓存
		return (number) => cache[number] || (cache[number] = fn(number))
	} 
	
	const calculation = (number) => {
		if (number === 0) {
			return 1;
		}
		
		console.log(number)
		return number * factorial(number - 1);	//	递归
	}
	
	const factorial = cacheFn(calculation)
	
	factorial(3);
	console.log('---------------------');
	factorial(5);

    运行结果如下:

在这里插入图片描述

    简单说一下这段代码,这就是一个简单的求阶乘,相信大家也都做过(maybe用C),factorial是用来获取阶乘结果的函数,cacheFn是用来设置缓存的函数,calculation是用来递归计算阶乘的函数。和以往不同的是,我们不再是直接运行calculation,而是运行经由cacheFn包装返回的函数factorial

    cacheFn在运行之后会返回一个函数,并且闭包一个变量cache,之后的每次计算都会先查看cache中是否已经有了相关的结果,才会去判断是否要执行calculation这个函数。而这个cache变量是只有cacheFn内部可以访问的,外部访问不到[1]。虽然这个例子很简单,但是仔细看你会发现,上面涉及到的几个函数,都是纯函数[2],这使得我们可以大胆的嵌套这几个函数,而不用操心外部环境变化而带来的不确定性。

[1](因为cacheFn返回的函数中保留了对cache的引用,所以在cacheFn运行完毕之后,cache这个变量的内存没有被js的垃圾回收机制所回收,但是由于外部不存在这个变量的引用,所以这个变量实际上也就变成了内部的一个私有变量,这种感觉和java/ts啥的private有点像吧,但是由于这个引用会一直存在,所以会导致cache的内存一直处于被占用状态,也有可能导致内存泄漏等问题,这就需要手动置空引用了。)

[2] 纯函数,指的是不依赖外部运行环境的函数(不对外部环境产生任何副作用,也不引用外部数据,所需要的数据全部从参数获取),严格来说甚至应该必须包含输入输出(标准的纯函数式语言比如haskell是这样的-0-)。对于任何确定的参数,函数总是返回一个唯一确定且固定的值,这就像数学上对于函数的定义,对于任意一个给定的x,有且仅有一个与之相对应的y。wiki

    有了闭包之后我们其实就可以做很多好玩的事情了,因为可以仅仅在内部保留一个变量,所以也可以很好地实现诸如洗牌算法之类的了,或者像上面一样针对特定场景设置一个私有缓存类似的。

结?

    哇,比想象中的累很多,看函数式也有一段时间了,加上看rx之类的,真的是越发喜欢这种编程思想,所以想着开这么一坑给大家安利一波,但是的确很累啊=-=。写这么点花了几个小时,查东西乱七八糟的。
    当然了这仅仅也是第一篇,作为一个简单的介绍对于函数式编程(尽管肯定还有很多没介绍到的地方,我尽力了- -),下一篇的话可能会更多的写一些代码了,介绍一下高阶函数,以及什么柯里化偏函数乱七八糟的(?如果还有下一篇的话,有也不知道啥时候=-=)

猜你喜欢

转载自blog.csdn.net/qq_40164643/article/details/86624755