位置: 编程技术 - 正文

深入探讨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数学函数)

  • 收到个人开票会计分录怎么做
  • 小规模减免增值税要交企业所得税吗
  • 会计准则折旧年限规定最新
  • 电子发票上的字体大小
  • 应收账款无法收回会计分录
  • 物业公司临时工的工资可以进成本吗
  • 未认证的进项税账务处理
  • 公司注销后会计凭证保管年限
  • 发生检测费用时怎么入账
  • 非税收入一般缴款书可以抵扣吗
  • 营业账簿是什么意思
  • 支付境外咨询费代扣代缴企业所得税
  • 工程交税必须在工程地点交吗
  • 已认证的发票没领怎么办
  • 营改增对金融服务业税负的影响
  • 物流分公司怎么运作
  • 月底结转应交税费怎么弄
  • 建筑行业不管是什么行业
  • 公司股东认缴资质末到位导致公司破产应承担什么责任
  • 白酒消费税最低计税价格
  • 主营业务税金及附加包括什么
  • 库存商品售价
  • 局域网文件共享不稳定
  • 未计提的上一年企业所得税
  • 以前年度的账错了怎么办
  • 认缴制下实收资本可以一直为零吗
  • linux sed 行尾
  • 暂估入库结转成本后期怎么冲账
  • 代办退税账务处理
  • 普通发票红冲需要填信息表吗
  • pacis.exe - pacis是什么进程 有什么用
  • 应收股利的主要特点
  • 购进商品发生溢余的核算
  • uniapp下拉菜单
  • 个人出租车辆交税吗
  • yolov3目标检测
  • centos+php+coreseek+sphinx+mysql之一coreseek安装篇
  • 解决什么情况
  • 帝国cms怎么加自己的名字
  • 银行的抵债资产是否需要缴纳房产税
  • 受托代销的分录
  • 研发费用的会计处理方法
  • mybatis怎么用
  • 现金劳务收入会计分录
  • 函数的单调性
  • 学电脑的网站
  • 不是公司员工差旅费可以入差旅费吗
  • 企业股东变更流程及费用
  • 如何在sql server中已有数据库进行修改
  • 小规模减免附加税会计分录怎么做
  • 交强险和车船税在哪里买
  • 养老保险和工伤失业保险不在一个时间
  • 物业公司代收代付租金要开发票吗
  • 逐步测试法计算内含报酬率
  • 已计提教育费附加但是未扣除个税
  • 应收账款记账凭证怎么写
  • 预收账款的借贷方向增减
  • 年报超时了可以补报吗
  • 塑料行业税负率是多少
  • 健全的财务会计制度承诺函
  • 日记账公式怎么设置
  • mysql5.7.19 winx64安装配置方法图文教程(win10)
  • sql server常用
  • mysql数据库简单介绍
  • 游戏卡怎么打开
  • 删除默认操作系统选项
  • win edge
  • 电脑超频以后变得很卡
  • win11怎么关闭系统防火墙
  • cocos2d原理
  • cocos2dx入门
  • jQuery实现别踩白块儿网页版小游戏
  • jquery与ajax获取特殊字符实例详解
  • 文件夹怎么变成
  • unity3d spine
  • Android-Universal-Image-Loader最新框架解析
  • 盐城城南新区的邮政编码是多少号
  • 福利费是否计入成本费用
  • 江苏契税补贴怎么领取
  • 企业所得税的计算,收入是含税还是不含税
  • 免责声明:网站部分图片文字素材来源于网络,如有侵权,请及时告知,我们会第一时间删除,谢谢! 邮箱:opceo@qq.com

    鄂ICP备2023003026号

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

    友情链接: 武汉网站建设