资讯专栏INFORMATION COLUMN

javascript函数式编程入门小结

includecmath / 1902人阅读

摘要:前言最近花了不少时间接触学习的函数式的编程方式,而后为了加深理解,又去折腾。不过幸运的是,天生具备了函数式编程的基本元素,所以学习的起点不会太低。初接触第一个实例,函数式编程是如何做一个番茄炒鸡蛋的。

前言

最近花了不少时间接触学习javascript的函数式的编程方式,而后为了加深理解,又去折腾haskell。

不同于人们比较熟悉的命令式编程,如面向对象编程(oop),函数式编程(fp)是一种更加抽象,更加‘数学’的编程方式。
当然,也是一种更加‘痛苦’的编程方式,尤其是刚接触时,总是难以摆脱的命令式的思维方式,大脑回路总是会迷路。
不过幸运的是,javascript天生具备了函数式编程的基本元素,所以学习的起点不会太低。

初接触

第一个实例,函数式编程是如何做一个番茄炒鸡蛋的。
伪代码,对比oop:

Class Chef{
  cook(m1,m2){
    return m1+m2
  }
}
chef = new Chef
food = chef.cook("番茄","鸡蛋")
food //番茄炒蛋。

fp的方式

getMaterial(m){
  return function(){
    return m
  }
}
cook(getM1,getM2){
  return getM1()+getM2()
}
food = cook(getMaterial("番茄"),getMaterial("鸡蛋"));
food //番茄炒蛋

那么现在,站在内存(拟作:你)变化的角度上,这两者的区别之处。
oop

1.你面前出现了一个厨师

2.你前面出现了番茄,鸡蛋

3.厨师把番茄和鸡蛋炒在一起

4.厨师把番茄炒蛋装在盘子上

4.你获得了番茄炒蛋

fp

1.你拿一个空盘子,你决定弄点东西在上面

2.你面前出现了一个传说中的厨具。 //没错!小当家同款厨具,只要丢材料进去,它就能弄出美味佳肴!

3.你虽然没有材料,但幸运的是,你有两张藏宝图,分别标示了番茄和鸡蛋的位置。通过藏宝图,就能找到所需的材料。

4.你把两张藏宝图扔到厨具里,告诉它,它得自己去找材料。 //传说中的厨具就是这么牛逼!

5.厨具获得了番茄

6.厨具获得了鸡蛋

7.厨具终于炒了番茄和鸡蛋

7.finally,你获得了番茄炒蛋

对比一下这个过程,可以发现:

oop方式总是是在告诉系统,第一步应该干什么(搞个厨师)然后干什么(弄到番茄和鸡蛋)、按部就班,最后你就能得到想要的值(番茄炒蛋)。

fp方式呢,恰恰相反,它是惰性的。只有你需要什么的时候,函数才会运算,才会返回数值,而不是一开始就存在的。

就好像学渣考90分,是因为在考试之前,他努力学习,到了90分。
这是结果。
而学霸考90分,只是因为考试的时候,做到90分时,懒癌发作,不想做题了。
这是过程。

fp的特性

这里列举了当前接触到fp中编程思想中的几个重要特性

1.不可变数据
2.函数是一等公民,即能作为参数,也可以是返回值
3.惰性求值

1.不可变数据

由于fp中都是函数,为了保证程序的可靠性,同样的参数,传入同一套的函数中,必须保证结果也是一样的。如:

let o = {name:"zhouyg"};
r1 = fn1(fn2(fn3(o)))
r2 = fn1(fn2(fn3(o)))
r1 === r2 //true

在javascript中的由于Array和Object的类型都是引用传递的。如果在函数内部改变了改变了原始o的值,那么改变了原始o的值,那么必然导致r1和r2的结果不一样。导致程序不可靠,不可维护。
这是javascript的特性引起的,需要额外的手段补救。

每次传递Object和Array时候,都做一个拷贝,使用拷贝后的对象作为函数参数

或者使用某些数据结构工具,例如F家著名的immutable.js

2.函数是一等公民

javascript天然满足,常见的各种回调。

3.惰性求值

顾名思义,只有在需要用到的才去计算。这里强行设定一种情景,如一个加法函数:
没有惰性求值

function add(n1,n2){
  if(n1<5){
    return n1
  }else{
    return n1+n2
  }
}
result = add(add(1,2),add(3,4)) //相当于add(3,4)的计算是浪费的。
result//3

惰性求值

function add(n1,n2){
  return n1+n2;
}
function preAdd(n1,n2){
  return function(){
    return add(n1,n2)
  }
}
function doAdd(fn1,fn2){
  n = fn1()
  if(n<5){
    return n     //只需要运行fn1,得到一个计算结果即可。
  }else{
    return add(fn1,fn2())
  }
}
result = doAdd(preAdd(1,2),preAdd(3,4))
result//10

对比一下可知,在javascript中的惰性求值,相当于先把参数先缓存着,return一个真正执行的计算的函数,等到需要结果采去执行。
这样的好处在于比较节省计算,尤其有时候这个在函数是不一定需要这个参数的时候。

最后

这里只是简单的回溯最近学习的fp的相关内容。并不是为了比较fp方式和其它编程方式的优劣,而是希望能够站在另外的一个角度,活跃大脑的思维,开拓视野,以更丰富的姿势来解决问题,毕竟俗话说得好,姿势就是力量。

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

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

相关文章

  • 前端_JavaScript

    摘要:为此决定自研一个富文本编辑器。例如当要转化的对象有环存在时子节点属性赋值了父节点的引用,为了关于函数式编程的思考作者李英杰,美团金融前端团队成员。只有正确使用作用域,才能使用优秀的设计模式,帮助你规避副作用。 JavaScript 专题之惰性函数 JavaScript 专题系列第十五篇,讲解惰性函数 需求 我们现在需要写一个 foo 函数,这个函数返回首次调用时的 Date 对象,注意...

    Benedict Evans 评论0 收藏0
  • Javascript函数编程小结

    摘要:源起函数式编程近几年非常流行经常可以在网上看到别人讨论相关话题我机缘巧合之下在上看到有人提到一个讲函数式编程的视频看过之后突然茅塞顿开瞬间把之前零碎的关于函数式编程的知识一下子都联系了起来于是自己希望趁有空把这些知识总结一下这样既可以回顾下 源起 函数式编程近几年非常流行,经常可以在网上看到别人讨论相关话题. 我机缘巧合之下在github上看到有人提到一个讲js函数式编程的视频,看过之...

    zengdongbao 评论0 收藏0
  • 编程 —— 函数编程入门

    摘要:在函数式编程中数据在由纯函数组成的管道中传递。函数式编程中函子是实现了函数的容器下文中将函子视为范畴,模型可表示如下但是在函数式编程中要避免使用这种面向对象的编程方式取而代之对外暴露了一个的接口也称为。 showImg(https://segmentfault.com/img/remote/1460000018101204); 该系列会有 3 篇文章,分别介绍什么是函数式编程、剖析函数...

    flyer_dev 评论0 收藏0
  • 编程模型(范小结

    摘要:参考链接面向对象编程模型现在的很多编程语言基本都具有面向对象的思想,比如等等,而面向对象的主要思想对象,类,继承,封装,多态比较容易理解,这里就不多多描述了。 前言 在我们的日常日发和学习生活中会常常遇到一些名词,比如 命令式编程模型,声明式编程模型,xxx语言是面向对象的等等,这个编程模型到处可见,但是始终搞不清是什么?什么语言又是什么编程模型,当你新接触一门语言的时候,有些问题是需...

    miya 评论0 收藏0

发表评论

0条评论

includecmath

|高级讲师

TA的文章

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