函数式编程初探

函数式编程 ( Functional Programming ) 是一种以函数为基本的编程体式格局和代码组织体式格局,从顺序员的思绪上来讲,就是将顺序拆分并笼统成多个函数,再组装归去。

在JavaScript这门语言中,函数是一等国民,函数可以作为函数的参数,函数也可以返回一个函数,因而合适函数式编程作风。

函数式作风的编程,善于数据的处置惩罚,且所谓“处置惩罚”并不改变数据自身。JavaScript中,数据老是以对象的情势涌现,也就是说,函数式的编程关于“吸收对象A→处置惩罚→处置惩罚→处置惩罚→得出新对象B”如许的流程可以很文雅地完成,且不影响对象A自身。

关于JavaScript顺序员(无论是前端照样后端),最常见且有用的编程形式当然是笼统出类(以组织函数的情势)并实例化,然后在实例上挪用要领。函数式作风的编程不是为了庖代这类编程形式,而是为了与之构成互补。

一些特征:

  • 不改变输入的数据

  • 不耦合,也就是说,函数只管不影响以至晓得外部的状况

  • 坚持数据组织情势的简朴,比方,只管运用JavaScript原生的数据结构(对象、数组等)

函数

在函数式编程中,任何代码可以都是函数,且请求具有返回值,以下示例

// 非函数式
var title = "Functional Programming";
var saying = "This is not";
console.log(saying + title); // => This is not Functional Programming

// 函数式
var say = title => "This is " + title; 
var text = say("Functional Programming"); // => This is Functional Programming

纯函数

纯函数在这里指函数内外间是“无”关联的。主要有下面两点
没有副作用(side effect)
不会涉及到外部变量的运用或修正
援用通明
函数内只会依靠传入参数,在任何时候对函数输入雷同的参数时,总能输出雷同的效果

// 非纯函数(函数内依靠函数外的变量值)
var title = "Functional Programming";
var say = ()=> "This is not" + title;   // <= 依靠了全局变量 title

// 纯函数
var say = (title)=>"This is " + title; // <= 依靠了以参数 title 传入
say("Functional Programming");

不可变数据(immutable)

这里主假如指变量值的不可变。当须要基于原变量值改变时,可通过发生新的变量来确保原变量的稳定性,以下

// 可变数据
 
var arr = ["Functional", "Programming"];
arr[0] = "Other"; // <= 修正了arr[0]的值
console.log(arr)  // => ["Other", "Programming"] // 变量arr值已被修正

// 不可变数据
 
var arr = ["Functional", "Programming"];
// 获得新的变量,不修正了本来的值
var newArr = arr.map(item => {
    if(item === "Functional"){
        return "Other"; 
    } else {
        return item;
    }
})
 
console.log(arr);  // => ["Functional", "Programming"] 变量arr值稳定
console.log(newArr); // => ["Other", "Programming"]  发生新的变量newArr

之所以运用这类稳定值,除了更好的函数式编程外,还可以保持线程安全可靠,实际上也能让代码越发清楚。
想象,假如你定义了一个变量A,A在其他处所被其他人修正了,如许是不方便定位A的当前值的。
运用 map, reduce 等数据处置惩罚函数
壮大的 JavaScript 有着越来越多的高能处置惩罚数据函数,个中包含了 map、 reduce、 filter 等。
map 可以对原数组中的值举行逐一处置惩罚并发生新的数组,一个简朴例子

// map
var data = [1, 2, 3];
var squares = data.map( (item, index, array) =>  item * item );
console.log(squares); // => [1, 4, 9]
console.log(data);// =>  [1, 2, 3] data 照样谁人 data 

reduce 可以对原数组中的各个值举行连系处置惩罚,来发生新的值,以下面例子中,previous 代表上一个值,current 代表当前值,reduce 函数可以传入第二个参数作为 previous 初始值,不传时则 previous 初始值为数组中第一个值。

// reduce
var sum = [1, 2, 3].reduce( (previous, current, index, array) => previous + current );
console.log(sum); // => 6

函数柯里化 Currying

柯里化 是将多参函数转换成一系列的单参函数。连系下面例子来讲明下

// 一个多参函数
var add = (a, b) => a + b;
add(1, 2); // => 3

将上面的多参函数举行柯里化,以下

// 柯里化函数
 
var add = a => b => a + b;

上面柯里化后的函数挪用体式格局也有所改变,第一次传入一个参数返回了一个函数,再传入参数则完成团体的挪用,这也是应用的闭包的特征

var add1 = add(1);
add1(2);  // => 3

柯里化后的函数,也可以应用在临盆 “ 函数 ” 上,以下示例

var say = title => type => title + " is " + type;
 
var sayFP = say("Functional Programming");
var sayOther = say("Other Programming");
 
sayFP("good"); // => Functional Programming is good
sayOther("good"); // => Other Programming is good

组合函数 compose

望文生义,组合函数是将多个函数举行组合成一个函数。举个例子

var compose = (fn1, fn2) => (arg) => fn1(fn2(arg));
 
var a = arg => arg + 'a';
var b = arg => arg + 'b';
 
var c = compose(a, b); // 将a,b函数举行组合
c('c');  // => cba

上面示例中,当挪用组合函数 c 时,传入的参数会经由 b 函数,接着将 b 函数的返回值作为 a 函数的参数值,从而输出终究效果。
组合函数 c 就像管道一样,将水流( 返回值 )流经各个函数中举行处置惩罚。

    原文作者:wtgzczz
    原文地址: https://segmentfault.com/a/1190000006996119
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞