位置: 编程技术 - 正文

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

  • 耕地占用税中的耕地是指什么
  • 当月认证发票进项税转出能不能第二个月转出
  • 个人出租房屋需要办理什么手续
  • 分公司亏损总公司怎么办
  • 打印的电子发票需要盖章么
  • 固定资产报废需要哪些人签字
  • 农产品核定扣除增值税进项税额计算表
  • 无偿捐赠设备该如何做账务处理呢?
  • 发票额开多了多出的金额怎么处理?
  • 案例分析房租完税证明怎么入账?
  • 如何查询已开出的增值税发票是否被认证
  • 个人所得税反推器
  • 现金收款能开专用发票吗
  • 怎么查找地方教育附加税的计税依据?
  • 个人独资企业是什么意思
  • 出口货物怎么开具发票
  • 进项税未抵扣会计分录
  • 个税汇算清缴包含退休金吗
  • 印花税减免需要做账吗现在
  • 外贸 代理
  • 刚毕业的学生可以买学生票吗
  • 用支票购入厂部办公用品2000元,车间办公用品1000元
  • PHP:imagesetstyle()的用法_GD库图像处理函数
  • print-js
  • 政府财政会计核算基础是什么
  • 固定资产投资账务处理
  • uniapp route
  • php解析配置文件
  • 基于yolov5的目标检测实验任务
  • php session用法
  • php验证码扭曲效果怎么做
  • 注册资本认缴可以增加吗
  • trainer 平替
  • 2021前端热门技术解读
  • 限定性和非限定性资产的区别
  • 微擎最新破解版
  • python中的split函数
  • cookie 会话
  • 帝国cms模型
  • 借款单属于外来单据吗
  • 纳税减免申报
  • 小规模纳税人三减一政策
  • 所得税申报表里季初资产是指什么
  • 饭店开业多久可以正常
  • 关于赠品的财务处理
  • 存货抵债如何做分录
  • 劳务费无发票怎么处理
  • 工资汇算清缴前发
  • 增值税销项税率是多少
  • 汽车以租代售合法吗
  • 展会赠品
  • 财务报表中预收账款
  • 土地的入账科目
  • 质保金可以先不开票吗
  • 发票已开后 对方公司名称变更怎么处理?
  • 职工薪酬的范围及内容
  • 如何学会计做账视频
  • mysql5.7.24安装配置教程
  • 电脑如何将耳机模式换扬声器
  • mac怎么复制粘贴文件夹
  • centos6.10配置网络
  • ubuntu 16.10
  • windows xp 配置
  • win10外置光驱读不出光盘怎么办
  • linux更改
  • win10无法安装无线显示器
  • linux配置静态
  • ajax 编码
  • Unity3D游戏开发培训课程大纲
  • shell中的-le
  • 分享一下相亲时碰见过哪些奇葩事
  • Qualcom QMI系列-基本知识介绍
  • jquery配合.NET实现点击指定绑定数据并且能够一键下载
  • linux 打包
  • ubuntu修改默认桌面环境
  • python中django框架
  • 小额贷款公司在职人员和离职人员情节哪种轻
  • 国家税务总局56号
  • 印花税核算有两种情况,是如何处理的?
  • 税务征收社保费
  • 免责声明:网站部分图片文字素材来源于网络,如有侵权,请及时告知,我们会第一时间删除,谢谢! 邮箱:opceo@qq.com

    鄂ICP备2023003026号

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

    友情链接: 武汉网站建设