0

0

JavaScript 函数式编程中的 curry 实现

黄舟

黄舟

发布时间:2017-03-02 14:53:09

|

1489人浏览过

|

来源于php中文网

原创

最近在学习javascript函数式编程,对其中大名鼎鼎的curry十分感兴趣,curry函数可以接受一个函数,我们暂且称之为原始函数,返回的也是一个函数,柯里化函数,这个返回的柯里化函数功能十分强大,他在执行的过程中,不断的返回一个贮存了传入参数的函数,直到触发了原始函数执行的条件。这么说比较概括,那么就举个例子来说明一下:

原始函数:

var add = (x, y) => x + y

柯里化函数:

 var curryAdd = curry(add)

这个add需要两个参数,但是我们的curryAdd执行可以传入更少的参数,当传入的参数少于add需要的参数的时候,add函数并不会执行,curryAdd就会将这个参数记下来,并且返回另外一个函数,这个函数可以继续执行传入参数,我们会有一个变量专门记录传入参数的情况,如果传入参数的总数等于add需要参数的总数,我们就激活了原始参数执行,就会返回我们想要的结果。

立即学习Java免费学习笔记(深入)”;

// 此时只传入了一个参数 根据判断返回的是一个函数
    var add2 = curryAdd(2)
    // add2 = function(...) {}
// 此时累计传入了两个参数 等于了add需要参数的总和 所以返回的是一个结果
    // 相当于执行了add(2)(3)
    var result = add2(3)
    // result = 5

还是很不错的是吧,好吧,我们的目的是为了写出这个神奇curry函数,而且还要一行写出来,不要着急,先分析一下怎么去写,然后再一步步的优化。

那根据上面的描述,我们看一下curry函数需要什么,首先需要一个变量,用来存下来原始函数的参数个数,我们知道function有一个属性为length,对就是它,我们用limit存下来

    var curry = function(fn) {
         var limit = fn.length
         ...
    }

curry函数要返回一个函数, 这个函数是要执行的,那么问题就是,我们要判断这个函数的执行是否激活了原始函数的执行,问题就出现在传入的参数上面。返回函数还是结果?这的确是一个问题,我们先写返回结果的情况,当传入的参数等于原始函数需要的参数时,我们执行原始函数fn

    var curry = function(fn) {
         var limit = fn.length
         return function (...args) {
             if (args.length >= limit) {
                 return fn.apply(null, args)
             }
         }
    }

否则呢 我们就要返回一个贮存了参数的函数,这里有两点,一是参数的传入历史我们要记录下来,二是这个返回的函数需要做些什么

极限网络办公Office Automation
极限网络办公Office Automation

专为中小型企业定制的网络办公软件,富有竞争力的十大特性: 1、独创 web服务器、数据库和应用程序全部自动傻瓜安装,建立企业信息中枢 只需3分钟。 2、客户机无需安装专用软件,使用浏览器即可实现全球办公。 3、集成Internet邮件管理组件,提供web方式的远程邮件服务。 4、集成语音会议组件,节省长途话费开支。 5、集成手机短信组件,重要信息可直接发送到员工手机。 6、集成网络硬

下载
    var curry = function(fn) {
         var limit = fn.length
         return function (...args) {
             if (args.length >= limit) {
                 return fn.apply(null, args)
             } else {
                 return function(...args2) {

                 }
             }
         }
    }

看出来了吧 我们只需要把返回函数执行的参数累加起来就达到了记录参数传入情况的目的,于是我们想到了concat 对 args.concat(args2), 依次类推,我们返回的函数要做的就是重复做上面的事情,也就是参数为args的函数要做的事情,所以他需要一个名字,不然我们没法执行,我们叫它judgeCurry

所以正如我们所说的,要么返回一个函数,要么执行原始函数。

    var curry = function(fn) {
         var limit = fn.length
         return function judgeCurry (...args) {
             if (args.length >= limit) {
                 return fn.apply(null, args)
             } else {
                 return function(...args2) {
                     return judgeCurry.apply(null, args.concat(args2))                                     
                 }
             }
         }
    }

我们终于写完了这个神奇的curry函数,它真的很强大,配合compose,那真是一个字,爽。

我们的目的还是一行把上面那个函数写出来,一行写?怎么写?对了,用ES6啊,于是一番折腾

var currySingle = fn => judgeCurry = (...args) => args.length >= fn.length ? fn.apply(null, args) : 
(...args2) => judgeCurry.apply(null, args.concat(args2))

好,我们看一下哪有问题,对了,就是我们为了不用limit参数,用了就得赋值,赋值就不能一行搞定了,就会变成这样

    var currySingle = fn => {
        var limit = fn.length
        var judgeCurry = null
        return judgeCurry = (...args) => args.length >= limit ? fn.apply(null, args) : (...args2) => judgeCurry.apply(null, args.concat(args2))
    }

需要判断参数的时候不断的对fn.length求值,但是fn.length的值是确定的,我们不想每次都求值,但又不想用limit怎么办,有什么办法呢?你一定想到了,立即执行函数!!

var currySingle = fn => ((limit) => judgeCurry = (...args) => args.length >= limit ? fn.apply(null, args) : 
(...args2) => judgeCurry.apply(null, args.concat(args2)))(fn.length)

不得不感叹javascript的神奇,终于,我们就一行将这个神奇的curry写出来了。

 以上就是JavaScript 函数式编程中的 curry 实现 的内容,更多相关内容请关注PHP中文网(www.php.cn)!

热门AI工具

更多
DeepSeek
DeepSeek

幻方量化公司旗下的开源大模型平台

豆包大模型
豆包大模型

字节跳动自主研发的一系列大型语言模型

通义千问
通义千问

阿里巴巴推出的全能AI助手

腾讯元宝
腾讯元宝

腾讯混元平台推出的AI助手

文心一言
文心一言

文心一言是百度开发的AI聊天机器人,通过对话可以生成各种形式的内容。

讯飞写作
讯飞写作

基于讯飞星火大模型的AI写作工具,可以快速生成新闻稿件、品宣文案、工作总结、心得体会等各种文文稿

即梦AI
即梦AI

一站式AI创作平台,免费AI图片和视频生成。

ChatGPT
ChatGPT

最最强大的AI聊天机器人程序,ChatGPT不单是聊天机器人,还能进行撰写邮件、视频脚本、文案、翻译、代码等任务。

相关专题

更多
C++ 设计模式与软件架构
C++ 设计模式与软件架构

本专题深入讲解 C++ 中的常见设计模式与架构优化,包括单例模式、工厂模式、观察者模式、策略模式、命令模式等,结合实际案例展示如何在 C++ 项目中应用这些模式提升代码可维护性与扩展性。通过案例分析,帮助开发者掌握 如何运用设计模式构建高质量的软件架构,提升系统的灵活性与可扩展性。

0

2026.01.30

c++ 字符串格式化
c++ 字符串格式化

本专题整合了c++字符串格式化用法、输出技巧、实践等等内容,阅读专题下面的文章了解更多详细内容。

0

2026.01.30

java 字符串格式化
java 字符串格式化

本专题整合了java如何进行字符串格式化相关教程、使用解析、方法详解等等内容。阅读专题下面的文章了解更多详细教程。

0

2026.01.30

python 字符串格式化
python 字符串格式化

本专题整合了python字符串格式化教程、实践、方法、进阶等等相关内容,阅读专题下面的文章了解更多详细操作。

0

2026.01.30

java入门学习合集
java入门学习合集

本专题整合了java入门学习指南、初学者项目实战、入门到精通等等内容,阅读专题下面的文章了解更多详细学习方法。

19

2026.01.29

java配置环境变量教程合集
java配置环境变量教程合集

本专题整合了java配置环境变量设置、步骤、安装jdk、避免冲突等等相关内容,阅读专题下面的文章了解更多详细操作。

16

2026.01.29

java成品学习网站推荐大全
java成品学习网站推荐大全

本专题整合了java成品网站、在线成品网站源码、源码入口等等相关内容,阅读专题下面的文章了解更多详细推荐内容。

17

2026.01.29

Java字符串处理使用教程合集
Java字符串处理使用教程合集

本专题整合了Java字符串截取、处理、使用、实战等等教程内容,阅读专题下面的文章了解详细操作教程。

2

2026.01.29

Java空对象相关教程合集
Java空对象相关教程合集

本专题整合了Java空对象相关教程,阅读专题下面的文章了解更多详细内容。

6

2026.01.29

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
React 教程
React 教程

共58课时 | 4.3万人学习

TypeScript 教程
TypeScript 教程

共19课时 | 2.5万人学习

Bootstrap 5教程
Bootstrap 5教程

共46课时 | 3.1万人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号