声明式和命令式编程
声明式和命令式编程 声明式(declarative)是结果导向的,命令式(imperative)是过程导向的 命令式编程:命令“机器”如何去做事情(how),这样不管你想要的是什么(what),它都会按照你的命令实现。 声明式编程:告诉“机器”你想要的是什么(what),让机器想出如何去做(how)。 声明式编程和命令式编程的代码例子 举个简单的例子,假设我们想让一个数组里的数值翻倍。 我们用命令式编程风格实现,像下面这样: 1 2 3 4 5 6 7 8 9 10 11 var numbers = [1,2,3,4,5] var doubled = [] for(var i = 0; i < numbers.length; i++) { var newNumber = numbers[i] * 2 doubled.push(newNumber) } console.log(doubled) //=> [2,4,6,8,10] 我们直接遍历整个数组,取出每个元素,乘以二,然后把翻倍后的值放入新数组,每次都要操作这个双倍数组,直到计算完所有元素。 而使用声明式编程方法,我们可以用 Array.map 函数,像下面这样: v v } c a a ) o r r r n e s n d t o u o u l m u r e b b n . e l l r e n o s d g ( = = d 2 o [ n u 1 u b , m l 2 b e , e d 3 r ) , s 4 . , m / 5 a = ] p > ( f [ u 2 n , c 4 t , i 6 o , n 8 ( , n 1 ) 0 ] { map 利用当前的数组创建了一个新数组,新数组里的每个元素都是经过了传入map的函数(这里是function(n) { return n*2 })的处理。 map函数所作的事情是将直接遍历整个数组的过程归纳抽离出来,让我们专注于描述我们想要的是什么(what)。注意,我们传入map的是一个纯函数;它不具有任何副作用(不会改变外部状态),它只是接收一个数字,返回乘以二后的值。 在一些具有函数式编程特征的语言里,对于list数据类型的操作,还有一些其他常用的声明式的函数方法。例如,求一个list里所有值的和,命令式编程会这样做: v v f } c a a o o r r r t n ( o s n t v t o u o a a l m t r l e b a . e l i + l r = o s = = g n ( = 0 0 u t ; m o [ b t 1 i e a , r l 2 < s ) , [ 3 n i , u ] / 4 m = , b > 5 e ] r 1 s 5 . l e n g t h ; i + + ) { 而在声明式编程方式里,我们使用 reduce 函数: v v } c a a ) o r r r ; n e s n t t o u o u l m t r e b a n . e l l r s o s = u g m ( = n t u + o [ m t 1 b n a , e l 2 r ) , s 3 . , r / 4 e = , d > 5 u ] c 1 e 5 ( f u n c t i o n ( s u m , n ) { reduce 函数利用传入的函数把一个 list 运算成一个值。它以这个函数为参数,数组里的每个元素都要经过它的处理。每一次调用,第一个参数(这里是sum)都是这个函数处理前一个值时返回的结果,而第二个参数(n)就是当前元素。这样下来,每此处理的新元素都会合计到sum中,最终我们得到的是整个数组的和。 同样,reduce 函数归纳抽离了我们如何遍历数组和状态管理部分的实现,提供给我们一个通用的方式来把一个 list 合并成一个值。我们需要做的只是指明我们想要的是什么 ...