资讯专栏INFORMATION COLUMN

函数式编程初探

oogh / 1319人阅读

摘要:函数式编程是一种以函数为基础的编程方式和代码组织方式,从程序员的思路上来说,就是将程序拆分并抽象成多个函数,再组装回去。在这门语言中,函数是一等公民,函数可以作为函数的参数,函数也可以返回一个函数,因此适合函数式编程风格。

函数式编程 ( 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 就像管道一样,将水流( 返回值 )流经各个函数中进行处理。

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/87930.html

相关文章

  • [python] 初探'函数编程'

    摘要:前言继续向下看廖大教程,看到了函数式编程这一节,当时是觉得没啥用直接跳过了,这次准备要仔细看一遍了,并记录下一些心得。 前言 继续向下看廖大教程,看到了函数式编程这一节,当时是觉得没啥用直接跳过了,这次准备要仔细看一遍了,并记录下一些心得。 函数式编程 上学期有上一门叫 人工智能 的课,老师强行要我们学了一个叫做 prolog 的语言,哇那感觉确实难受,思维方式完全和之前学过的不一样,...

    xcc3641 评论0 收藏0
  • 深入React知识点整理(一)

    摘要:以我自己的理解,函数式编程就是以函数为中心,将大段过程拆成一个个函数,组合嵌套使用。越来越多的迹象表明,函数式编程已经不再是学术界的最爱,开始大踏步地在业界投入实用。也许继面向对象编程之后,函数式编程会成为下一个编程的主流范式。 使用React也满一年了,从刚刚会使用到逐渐探究其底层实现,以便学习几招奇技淫巧从而在自己的代码中使用,写出高效的代码。下面整理一些知识点,算是React看书...

    Gilbertat 评论0 收藏0
  • vue实现原理初探

    摘要:数据和视图的分离更符合面向对象的编程,的实现也是和一样用虚拟来实现的,至于什么是虚拟,就是用通过模板渲染而成的。 Vue是当今热门的框架,他可以进行数据双向绑定,为什么vue会大受欢迎,我知道的原因大致如下?1.传统改变dom结构的操作是非常浪费性能的操作(就是慢)2.把dom结构改变的逻辑放在js层来做可以提高性能。3.数据和视图的分离更符合面向对象的编程,mvvm vue的实现也是...

    Cristic 评论0 收藏0
  • 初探Kotlin+SpringBoot联合编程

    摘要:是一门最近比较流行的静态类型编程语言,而且和一样同属系。这个生成的构造函数是合成的,因此不能从或中直接调用,但可以使用反射调用。 showImg(https://segmentfault.com/img/remote/1460000012958496); Kotlin是一门最近比较流行的静态类型编程语言,而且和Groovy、Scala一样同属Java系。Kotlin具有的很多静态语言...

    xiaokai 评论0 收藏0
  • 初见函数编程

    摘要:在学习的过程中时常会听到一个名次函数式编程,那么究竟什么是函数式编程,函数式编程又有什么优点,这就在这篇博客进行一个简单的总结吧主要内容函数式编程的概念函数式编程的优点与示例什么是函数式编程首先,我们放下编程的概念,我们来看函数。 在学习 JS 的过程中时常会听到一个名次——函数式编程,那么究竟什么是函数式编程,函数式编程又有什么优点,这就在这篇博客进行一个简单的总结吧~ 主要内容: 函...

    jerryloveemily 评论0 收藏0

发表评论

0条评论

最新活动
阅读需要支付1元查看
<