位置: 编程技术 - 正文

深入探讨javascript函数式编程(深入探讨换个说法怎么说)

编辑:rootadmin

推荐整理分享深入探讨javascript函数式编程(深入探讨换个说法怎么说),希望有所帮助,仅作参考,欢迎阅读内容。

文章相关热门搜索词:深入探讨是什么意思,深入探讨新时代雷锋精神的内涵和价值,深入探讨的成语,深入探讨交流,深入探讨是什么意思,深入探讨是什么意思,深入探讨是什么意思,深入探讨交流,内容如对您有帮助,希望把文章链接给更多的朋友!

函数式编程全都是关于如何把一个问题分解为一系列函数的。通常,函数会链在一起,互相嵌套, 来回传递,被视作头等公民。如果你使用过诸如jQuery或Node.js这样的框架,你应该用过一些这样的技术, 只不过你没有意识到。

我们从Javascript的一个小尴尬开始。

假设我们需要一个值的列表,这些值会赋值给普通的对象。这些对象可能包含任何东西:数据、HTML对象等等。

这个代码能用但是不稳定。任何代码都可以不通过accumulate()函数改变values对象。 而且如果我们忘记了给values赋上空数组[],这个代码压根儿就不会工作。

但是如果变量声明在函数内部,他就不会被任何捣蛋的代码给更改。

不行呀!只有最后传入的那个对象的值才被返回。

我们也许可以通过在第一个函数内部嵌套一个函数来解决这个问题。

可是问题依然存在,而且我们现在无法访问accumulate函数和values变量了。

我们需要的是一个自调用函数

自调用函数和闭包

如果我们能够返回一个可以依次返回values数组的函数表达式怎么样?在函数内声明的变量可以被函数内的所有代码访问到, 包括自调用函数。

通过使用自调用函数,前面的尴尬消失了。

这些都是关于作用域的。变量values在内部函数accumulate()中可见,即便是在外部的代码在调用这个函数时。 这叫做闭包。

Javascript中的闭包就是函数可以访问父作用域,哪怕父函数已经执行完毕。

闭包是所有函数式语言都具有的特征。传统的命令式语言没有闭包。

高阶函数

自调用函数实际上是高阶函数的一种形式。高阶函数就是以其它函数为输入,或者返回一个函数为输出的函数。

高阶函数在传统的编程中并不常见。当命令式程序员使用循环来迭代数组的时候,函数式程序员会采用完全不同的一种实现方式。 通过高阶函数,数组中的每一个元素可以被应用到一个函数上,并返回新的数组。

这是函数式编程的中心思想。高阶函数具有把逻辑像对象一样传递给函数的能力。

在Javascript中,函数被作为头等公民对待,这和Scheme、Haskell等经典函数是语言一样的。 这话听起来可能有点古怪,其实实际意思就是函数被当做基本类型,就像数字和对象一样。 如果数字和对象可以被来回传递,那么函数也可以。

来实际看看。现在把上一节的ValueAccumulator()函数配合高阶函数使用:// 使用forEach()来遍历一个数组,并对其每个元素调用回调函数accumulator2var accumulator2 = ValueAccumulator();var objects = [obj1, obj2, obj3]; // 这个数组可以很大objects.forEach(accumulator2);console.log(accumulator2());

纯函数

纯函数返回的计算结果仅与传入的参数相关。这里不会使用外部的变量和全局状态,并且没有副作用。 换句话说就是不能改变作为输入传入的变量。所以,程序里只能使用纯函数返回的值。

用数学函数来举一个简单的例子。Math.sqrt(4)将总是返回2,不使用任何隐藏的信息,如设置或状态, 而且不会带来任何副作用。

纯函数是对数学上的“函数”的真实演绎,就是输入和输出的关系。它们思路简单也便于重用。 由于纯函数是完全独立的,它们更适合被一次又一次地使用。

举例说明来对比一下非纯函数和纯函数。

非纯函数依赖window对象的状态来计算宽度和高度,自给自足的纯函数则要求这些值作为参数传入。 实际上它就允许了信息打印到任何地方,这也让这个函数有了更多用途。

非纯函数看起来是一个更容易的选择,因为它在自己内部实现了追加元素,而不是返回元素。 返回了值的纯函数printSomewhere()则会在跟其他函数式编程技术的配合下有更好的表现。

当一个函数是纯的,也就是不依赖于状态和环境,我们就不用管它实际是什么时候被计算出来。 后面的惰性求值将讲到这个。

匿名函数

把函数作为头等对象的另一个好处是匿名函数。

深入探讨javascript函数式编程(深入探讨换个说法怎么说)

就像名字暗示的那样,匿名函数就是没有名字的函数。实际不止这些。它允许了在现场定义临时逻辑的能力。 通常这带来的好处就是方便:如果一个函数只用一次,没有必要给它浪费一个变量名。

下面是一些匿名函数的例子:

下面是匿名函数和高阶函数配合使用的例子

这里返回的那个函数不需要命名,它可以在powersOf()函数外的任何地方使用,这就是匿名函数。

还记得累加器的那个函数吗?它可以用匿名函数重写

真棒!一个高阶匿名纯函数。我们怎么这么幸运?实际上还不止这些,这里面还有个自执行的结构, (function(){...})();。函数后面跟的那个括号可以让函数立即执行。在上面的例子里, 给外面values赋的值是函数执行的结果。

匿名函数不仅仅是语法糖,他们是lambda演算的化身。请听我说下去…… lambda演算早在计算机和计算机语言被发明的很久以前就出现了。它只是个研究函数的数学概念。 非同寻常的是,尽管它只定义了三种表达式:变量引用,函数调用和匿名函数,但它被发现是图灵完整的。 如今,lambda演算处于所有函数式语言的核心,包括javascript。 由于这个原因,匿名函数往往被称作lambda表达式。

匿名函数也有一个缺点,那就是他们在调用栈中难以被识别,这会对调试造成一些困难。要小心使用匿名函数。

方法链

在Javascript中,把方法链在一起很常见。如果你使用过jQuery,你应该用过这种技巧。它有时也被叫做“建造者模式”。

这种技术用于简化多个函数依次应用于一个对象的代码。

这只有在函数是目标对象所拥有的方法时才有效。如果你要创建自己的函数,比如要把两个数组zip到一起, 你必须把它声明为Array.prototype对象的成员.看一下下面的代码片段: Array.prototype.zip = function(arr2) { // ...}

这样我们就可以写成下面的样子arr.zip([,,,).map(function(n){return n*2});// Output: 2, , 4, , 6, , 8,

递归

递归应该是最著名的函数式编程技术。就是一个函数调用它自己。

当函数调用自己,有时奇怪的事情就发生了。它的表现即是一个循环,多次执行同样的代码,也是一个函数栈。

使用递归函数时必须十分小心地避免无限循环(这里应该说是无限递归)。就像循环一样,必须有个停止条件。 这叫做基准情形(base case)。

下面有个例子

译注:原文中的代码有误,递归情形的函数调用缺少return,导致函数执行得最后没有结果。这里已经纠正。

递归和循环可以相互转换。但是递归算法往往更合适,甚至是必要的,因为有些情形用循环很费劲。

一个明显的例子就是遍历树。

分而治之

递归不只是代替for和while循环的有趣的方式。有个叫分而治之的算法,它递归地把问题拆分成更小的情形, 直到小到可以解决。

历史上有个欧几里得算法用于找出两个数的最大公分母

理论上来说,分而治之很牛逼,但是现实中有用吗?当然!用Javascript的函数对数组排序不是很好, 它不但替换了原数组,也就是说数据不是不变的,并且它还不够可靠、灵活。通过分而治之,我们可以做得更好。

全部的实现代码大概要行,这里只展示伪代码:

译注:关于用分而治之的思路进行排序的一个更好的例子是快排,使用Javascript也只有行代码。 具体请参考我以前的博文 《优雅的函数式编程语言》

惰性求值

惰性求值,也叫做非严格求值,它会按需调用并推迟执行,它是一种直到需要时才计算函数结果的求值策略, 这对函数式编程特别有用。比如有行代码是 x = func(),调用这个func()函数得到的返回值会赋值给x。 但是x等于什么一开始并不重要,直到需要用到x的时候。等到需要用x的时候才调用func()就是惰性求值。

这一策略可以让性能明显增强,特别是当使用方法链和数组这些函数式程序员最喜爱的程序流技术的时候。 惰性求值让人兴奋的一个优点是让无限序列成为可能。因为在它实在无法继续延迟之前,什么都不需要被真正计算出来。 它可以是这个样子:

这为很多可能性敞开了大门,比如异步执行、并行计算、组合,这只列举了一点。

然而,还有个问题,Javascript本身并不支持惰性求值,也就是说存在让Javascript模拟惰性求值的函数库, 这是第三章的主题。

javascript函数式编程程序员的工具集 如果你仔细看了到目前为止出现过的示例代码,你会发现这里面的一些方法不太熟悉。它们是map()、filter()和reduce()函数,它们对任何语言的函数式编程

JavaScript实现上下浮动的窗口效果代码 本文实例讲述了JavaScript实现上下浮动的窗口效果代码。分享给大家供大家参考。具体如下:这里介绍使用JavaScript实现上下浮动的窗口,在垂直方向上漂

关于事件mouseover ,mouseout ,mouseenter,mouseleave的区别 最近在做的在线考试和课程商城都遇到这样的问题:就是鼠标滑过的时候出现一个层,当鼠标滑到当前层的话mouseover和mouseout在低版本的浏览器会出现闪

标签: 深入探讨换个说法怎么说

本文链接地址:https://www.jiuchutong.com/biancheng/380310.html 转载请保留说明!

上一篇:Javascript函数式编程语言(js函数的使用规则)

下一篇:javascript函数式编程程序员的工具集(javascript数学函数)

  • 企业所得税如何做分录
  • 消费税退回退税流程
  • 进口货物的会计科目
  • 小规模减免的增值税怎么做账
  • 税务季报利润表的本年累计可以更改吗
  • 企业缴纳印花税通过什么科目
  • 社保基数申报怎么看是否成功
  • 本地的住宿费怎么交
  • 公积金做账需要计提吗怎么做
  • 模具费入什么会计科目
  • 其他应付款转为营业外收入要交税吗
  • 企业筹建期间开办费计入什么科目
  • 固定资产的资本化后续支出
  • 2018年用2015年的发票入账有什么税务的风险?
  • 待抵扣进项税贷方有余额什么意思
  • 企业申报表填写错误
  • 企业如何实现资源共享
  • 公益性捐赠公告
  • 维修费和配件能抵税吗
  • 什么是税收编码,在哪里查
  • 预付费服务是什么
  • 加工费计入什么费用
  • 直接快递到国外的货物如何收汇?
  • 建筑业简易征收进项税额转出
  • 企业收到票据时应以什么入账
  • 商业土地厂房办公房过户需要交什么税?
  • 不动产进项税额转出分录
  • 利息怎么算的计算公式举例
  • 第一次申领发票可以增额吗?
  • 电脑系统还原步骤
  • 关于商品退换
  • 往来账乱如何处理
  • windows10如何显示桌面图标
  • linux管理员账户名
  • 石炭纪的树有多高
  • 会计准则新规
  • dl.php怎么打开
  • 微信php接口
  • eyring模型
  • lincom命令
  • 在vue3项目中使用vue2
  • 织梦遍历栏目描述
  • 建筑企业未按规定预缴增值税
  • mysql @参数
  • 织梦程序
  • 怎么盘存货
  • 预收账款可以用什么科目核算
  • 教育类财务工作内容
  • 企业主营业务收入净额怎么算
  • 小公司财务做内账流程
  • 商场一般是怎么缴纳租金的
  • 当月计提的工资,次月申报吗
  • 银行只收不付解除方式
  • 员工休产假不发工资违法吗
  • 小微企业可以享受六税两费吗
  • 企业购买国债逆回购要交企业所得税吗
  • 核定征收也需要报税务报表吗?
  • 小规模一直零申报有什么影响
  • 短期借款利息是多少
  • 作废发票丢了罚款多少
  • Mysql inner join on的用法实例(必看)
  • ubuntu16.04英文版安装教程
  • ubuntu双显卡驱动安装
  • 苹果电脑怎么归类app
  • mis.off c n
  • nipc什么意思
  • javascript动画教程
  • android开发环境的搭建步骤
  • Lesson01_01 HTML基础
  • iframe用法和代码
  • css滚动条设置
  • json jquery
  • php开机启动
  • python的设置
  • python with 用法
  • 登录电子税务局显示时间错误如果解决
  • 现在哪个行业的税负很重了
  • 南京电子税务局咨询电话
  • 经营所得专项扣除养老保险费可以全额扣除吗
  • 济南车辆购置税完税证明电子版
  • 免责声明:网站部分图片文字素材来源于网络,如有侵权,请及时告知,我们会第一时间删除,谢谢! 邮箱:opceo@qq.com

    鄂ICP备2023003026号

    网站地图: 企业信息 工商信息 财税知识 网络常识 编程技术

    友情链接: 武汉网站建设