位置: 编程技术 - 正文

深入解析JavaScript中函数的Currying柯里化(深入解析抑郁症:什么是它的表现?别小看它的危害程度!)

编辑:rootadmin

推荐整理分享深入解析JavaScript中函数的Currying柯里化(深入解析抑郁症:什么是它的表现?别小看它的危害程度!),希望有所帮助,仅作参考,欢迎阅读内容。

文章相关热门搜索词:深入解析windows第7版卷2,深入解析java编译器:源码剖析与实例详解,深入解析windows第7版,深入解析抑郁症:什么是它的表现?别小看它的危害程度!,深入解析抑郁症:什么是它的表现?别小看它的危害程度!,深入解析windows第7版pdf,深入解析windows,深入解析什么意思,内容如对您有帮助,希望把文章链接给更多的朋友!

引子先来看一道小问题:有人在群里出了到一道题目:var s = sum(1)(2)(3) ....... 最后 alert(s) 出来是6 var s = sum(1)(2)(3)(4) ....... 最后 alert(s) 出来是 问sum怎么实现?刚看到题目,我第一反应是sum返回的是一个function,但是没有最终实现,印象中看到过类似的原理,但是记不清了。 后来同事说,这个是叫柯里化,实现方法比较巧妙:

下面我们就深入来看一下currying柯里化~

什么是柯里化?

柯里化是这样的一个转换过程,把接受多个参数的函数变换成接受一个单一参数(注:最初函数的第一个参数)的函数,如果其他的参数是必要的,返回接受余下的参数且返回结果的新函数。

当我们这么说的时候,我想柯里化听起来相当简单。JavaScript中是怎么实现的呢?假设我们要写一个函数,接受3个参数。

现在,假定我们有柯里化函数,能够把传统的JavaScript函数转换成柯里化后的函数:

手动柯里化

在上面的例子中,我们假定拥有神秘的curry函数。我会实现这样的函数,但是现在,我们首先看看为什么这样的函数是如此必要。举个例子,手动柯里化一个函数并不困难,但是确实有点???

在JavaScript,即使你不指定一个函数所有的参数,函数仍将被调用。这是个非常实用JavaScript的功能,但是却给柯里化制造了麻烦。

思路是每一个函数都是有且只有一个参数的函数。如果你想拥有多个参数,你必须定义一系列相互嵌套的函数。讨厌!这样做一次两次还可以,可是需要以这种方式定义需要很多参数的函数的时候,就会变得相当??潞湍延谠亩痢#ǖ?潜鸬P模?一崧砩细嫠吣阋桓霭旆ǎ?/p>

一些函数编程语言,像Haskell和OCaml,语法中内置了函数柯里化。在这些语言中,举个例子,每个函数是拥有一个参数的函数,并且只有一个参数。你可能会认为这种限制麻烦胜过好处,但是语言的语法就是这样,这种限制几乎无法察觉。

举个例子,在OCaml,你可以用两种方式定义上面example:

很容易看出这两个例子和上面的那两个例子是如何的相似。

区别,然而,是否在OCaml也是做了同样的事情。OCaml,没有拥有多个参数的函数。但是,在一行中声明多个参数就是嵌套定义单参函数“快捷方式”。

类似的 ,我们期待调用柯里化函数句法上和OCaml中调用多参函数类似。我们期望这样调用上面的函数:

而在JavaScript,我们采用明显不同的方式:

在OCaml这类语言中,柯里化是内置的。在JavaScript,柯里化虽然可行(高阶函数),但是语法上是不方便的。这也是为什么我们决定编写一个柯里化函数来帮我们做这些繁琐的事情,并使得我们的代码简洁。

创建一个curry辅助函数

理论上我们期望可以有一个方便的方式转换普通老式的JavaScript函数(多个参数)到完全柯里化的函数。

这个想法不是我独有的,其他的人已经实现过了,例如在wu.js 库中的.autoCurry()函数(尽管你关心的是我们自己的实现方式)。

首先,让我们创建一个简单的辅助函数 .sub_curry:

让我们花点时间看看这个函数的功能。相当简单。sub_curry接受一个函数fn作为它的第一个参数,后面跟着任何数目的输入参数。返回的是一个函数,这个函数返回fn.apply执行结果,参数序列合并了该函数最初传入参数的,加上fn调用的时候传入参数的。

看例子:

很明显,这并不是我门想要的,但是看起来有点柯里化的意思了。现在我们将定义柯里化函数curry:

这个函数接受两个参数,一个函数和要“柯里化”的参数数目。第二个参数是可选的,如果省略,默认使用Function.prototype.length 属性,就是为了告诉你这个函数定义了几个参数。

最终,我们能够论证下面的行为:

我知道你在想什么…

等等…什么?!

难道你疯了?应该是这样!我们现在能够在JavaScript中编写柯里化函数,表现就如同OCaml或者Haskell中的那些函数。甚至,如果我想要一次传递多个参数,我可以向我从前做的那样,用逗号分隔下参数就可以了。不需要参数间那些丑陋的括号,即使是它是柯里化后的。

这个相当有用,我会立即马上谈论这个,可是首先我要让这个Curry函数前进一小步。

深入解析JavaScript中函数的Currying柯里化(深入解析抑郁症:什么是它的表现?别小看它的危害程度!)

柯里化和“洞”(“holes”)

尽管柯里化函数已经很牛了,但是它也让你必须花费点小心思在你所定义函数的参数顺序上。终究,柯里化的背后思路就是创建函数,更具体的功能,分离其他更多的通用功能,通过分步应用它们。

当然这个只能工作在当最左参数就是你想要分步应用的参数!

为了解决这个,在一些函数式编程语言中,会定义一个特殊的“占位变量”。通常会指定下划线来干这事,如过作为一个函数的参数被传入,就表明这个是可以“跳过的”。是尚待指定的。

这是非常有用的,当你想要分步应用(partially apply)一个特定函数,但是你想要分布应用(partially apply)的参数并不是最左参数。

举个例子,我们有这样的一个函数:

也许我们想要定义一个新的函数,我们部分提供SendAjax函数特定的Options,但是允许url和data可以被指定。

当然了,我们能够相当简单的这样定义函数:

或者,使用使用约定的下划线方式,就像下面这样:

注意两个参数以下划线的方式传入。显然,JavaScript并不具备这样的原生支持,于是我们怎样才能这样做呢?

回过头让我们把curry函数变得智能一点…

首先我们把我们的“占位符”定义成一个全局变量。

我们把它定义成对象字面量{},便于我们可以通过===操作符来判等。

不管你喜不喜欢,为了简单一点我们就使用_来做“占位符”。现在我们就可以定义新的curry函数,就像下面这样:

实际代码还是有着巨大不同的。 我们这里做了一些关于这些“洞”(holes)参数是什么的记录。概括而言,运行的职责是相同的。

展示下我们的新帮手,下面的语句都是等价的:

疯狂吧?!

我为什么要关心?柯里化能够怎么帮助我?

你可能会停在这儿思考…

这看起来挺酷而且…但是这真的能帮助我编写更好的代码?

这里有很多原因关于为什么函数柯里化是有用的。

函数柯里化允许和鼓励你分隔复杂功能变成更小更容易分析的部分。这些小的逻辑单元显然是更容易理解和测试的,然后你的应用就会变成干净而整洁的组合,由一些小单元组成的组合。

为了给一个简单的例子,让我们分别使用Vanilla.js, Underscore.js, and “函数化方式” (极端利用函数化特性)来编写CSV解析器。

Vanilla.js (Imperative)

函数化方式

所有这些例子功能上是等价的。我有意的尽可能的简单的编写这些。

想要达到某种效果是很难的,但是主观上这些例子,我真的认为最后一个例子,函数式方式的,体现了函数式编程背后的威力。

关于curry性能的备注

一些极度关注性能的人可以看看这里,我的意思是,关注下所有这些额外的事情?

通常,是这样,使用柯里化会有一些开销。取决于你正在做的是什么,可能会或不会,以明显的方式影响你。也就是说,我敢说几乎大多数情况,你的代码的拥有性能瓶颈首先来自其他原因,而不是这个。

有关性能,这里有一些事情必须牢记于心:

存取arguments对象通常要比存取命名参数要慢一点 一些老版本的浏览器在arguments.length的实现上是相当慢的 使用fn.apply( … ) 和 fn.call( … )通常比直接调用fn( … ) 稍微慢点 创建大量嵌套作用域和闭包函数会带来花销,无论是在内存还是速度上 在大多是web应用中,“瓶颈”会发生在操控DOM上。这是非常不可能的,你在所有方面关注性能。显然,用不用上面的代码自行考虑。

Sort()函数的多种用法 sort()方法用于对数组的元素进行排序。包含于头文件algorithm语法arrayObject.sort(sortby)参数描述sortby可选。规定排序顺序。必须是函数。返回值对数组的引

详解Matlab中 sort 函数用法 (1)B=sort(A)对一维或二维数组进行升序排序,并返回排序后的数组,当A为二维时,对数组每一列进行排序.eg:A=[1,5,3],则sort(A)=[1,3,5]A=[1,5,3;2,4,1],则sort(A)=[1,4,1;2,5,

简述Matlab中size()函数的用法 size()函数用来获取矩阵的行数和列数。(1)s=size(A),当只有一个输出参数时,返回一个行向量,该行向量的第一个元素时矩阵的行数,第二个元素是

标签: 深入解析抑郁症:什么是它的表现?别小看它的危害程度!

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

上一篇:分享js粘帖屏幕截图到web页面插件screenshot-paste(分享js粘帖屏幕怎么弄)

下一篇:Sort()函数的多种用法(sort 函数)

  • 外出经营是什么意思
  • 税控是干什么用的
  • 表见代理通俗
  • 小规模纳税人为什么没有进项
  • 资源税的征税对象都是原矿和选矿
  • 小规模减免增值税要交企业所得税吗
  • 入股资金打进公司帐户要交税吗
  • 供应商属于应收账款吗
  • 外地预交的附加税金在申报的时候怎么填
  • 调整以前年度递延收益确认收入账务处理
  • 技改贴息资金的财务、会计及税收处理
  • 出口旧设备最新政策
  • 认缴制下实缴资本流程
  • 已核销的贷款收回计入什么科目
  • 涉税软件技术维护费可以全额抵扣吗?
  • 工商年报员工人数怎么算
  • 超出标准的公积金怎么交
  • 公司没有车牌可以买车吗
  • 公司单位员工餐费怎么算
  • 资产计税基础是怎么填
  • 企业怎么才能开100万发票
  • 一般纳税人企业所得税如何计算
  • 终于找到修改mac的方法了!
  • 税收返还的账务处理
  • 营业外支出是否需要发票
  • 微博 照片水印
  • 入库的原材料单价怎么求
  • 按销售收入比例分摊进项税额按月还是按年
  • 本月收到的发票可以下月勾选抵扣吗
  • 从银行提取现金准备发放工资
  • php自定义字段
  • vue数据更新会触发什么生命周期
  • 在缴纳企业所得税的情形
  • 自产产品用于应税项目为什么不考虑偷税
  • 应收账款和应付账款怎么对冲
  • php远程命令执行
  • 图书发票怎么开
  • PHP自定义函数实现计算机整数的四次方
  • php获取文件名称
  • 销售旧货怎么填写申报表
  • 筹办分公司
  • 进项税转出金额是发票上的哪个
  • 未分配利润为负数严重吗
  • phpcms模板制作教程
  • 履约保证金能否委托支付
  • 动产什么时候取得所有权
  • 装修店面装修费的会计分录
  • 差旅费报销范文
  • 小企业会计准则2023电子版
  • 合同权利义务包含债务吗
  • 个体户是什么样的
  • 股东借款的利息收入
  • 公司账户资金转个人账户
  • 会计手工做账的目的
  • 材料成本差异会计处理
  • 制造费用包括哪些内容科目
  • 高新技术产品收入归集依据
  • 付当月房租怎么做分录
  • 未开票州
  • 可抵扣的税票
  • SQL server 字符串函数
  • win8系统升级win8.1
  • drupdate
  • diy组装电脑前置怎么样
  • win8.1系统更新
  • win10个性化颜色在开始任务栏选不了
  • Android AsyncTaskLoader需要注意的问题
  • android基础知识大全
  • convert fs
  • python运行py文件没反应
  • 会用python
  • Android自定义控件高级进阶与精彩实例
  • 图片处理流程
  • dom4j解析xml字符串步骤
  • python守护线程与非守护线程
  • 广东税务APP实名可以注册两个吗?
  • 企业年金个人缴纳的辞职能拿吗
  • 个人所得税减免申报操作流程
  • 纳税服务理念2023
  • 免责声明:网站部分图片文字素材来源于网络,如有侵权,请及时告知,我们会第一时间删除,谢谢! 邮箱:opceo@qq.com

    鄂ICP备2023003026号

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

    友情链接: 武汉网站建设