0

0

JavaScript 函数式编程中 compose 实现

黄舟

黄舟

发布时间:2017-03-02 14:49:29

|

2008人浏览过

|

来源于php中文网

原创

上一篇文章介绍了javascript函数式编程中curry(柯里化)的实现,当然那个柯里化是有限参数的柯里化,等有机会在补上无限参数的那一种柯里化,这次主要说的是javascript函数式编程中另外一个很重要的函数composecompose函数的作用就是组合函数的,将函数串联起来执行,将多个函数组合起来,一个函数的输出结果是另一个函数的输入参数,一旦第一个函数开始执行,就会像多米诺骨牌一样推导执行了。

简介

比如有这样的需求,要输入一个名字,这个名字有由firstName,lastName组合而成,然后把这个名字全部变成大写输出来,比如输入jacksmith我们就要打印出来,‘HELLO,JACK SMITH’

我们考虑用函数组合的方法来解决这个问题,需要两个函数greeting, toUpper

var greeting = (firstName, lastName) => 'hello, ' + firstName + ' ' + lastName
var toUpper = str => str.toUpperCase()
var fn = compose(toUpper, greeting)
console.log(fn('jack', 'smith'))
// ‘HELLO,JACK SMITH’

这就是compose大致的使用,总结下来要注意的有以下几点

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

  • compose的参数是函数,返回的也是一个函数

  • 因为除了第一个函数的接受参数,其他函数的接受参数都是上一个函数的返回值,所以初始函数的参数是多元的,而其他函数的接受值是一元

  • compsoe函数可以接受任意的参数,所有的参数都是函数,且执行方向是自右向左的,初始函数一定放到参数的最右面

知道这三点后,就很容易的分析出上个例子的执行过程了,执行fn('jack', 'smith')的时候,初始函数为greeting,执行结果作为参数传递给toUpper,再执行toUpper,得出最后的结果,compose的好处我简单提一下,如果还想再加一个处理函数,不需要修改fn,只需要在执行一个compose,比如我们再想加一个trim,只需要这样做

var trim = str => str.trim()
var newFn = compose(trim, fn)
console.log(newFn('jack', 'smith'))

就可以了,可以看出不论维护和扩展都十分的方便。

动感购物HTML
动感购物HTML

修正了V1.10的一些BUG感购物HTML系统是集合目前网络所有购物系统为参考而开发,代码采用DIV编号,不管从速度还是安全我们都努力做到最好,此版虽为免费版但是功能齐全,无任何错误,特点有:专业的、全面的电子商务解决方案,使您可以轻松实现网上销售;自助式开放性的数据平台,为您提供充满个性化的设计空间;功能全面、操作简单的远程管理系统,让您在家中也可实现正常销售管理;严谨实用的全新商品数据库,便于

下载

实现

例子分析完了,本着究其根本的原则,还是要探究与一下compose到底是如何实现的,首先解释介绍一下我是如何实现的,然后再探求一下,javascript函数式编程的两大类库,lodash.jsramda.js是如何实现的,其中ramda.js实现的过程非常函数式。

我的实现

我的思路是,既然函数像多米诺骨牌式的执行,我首先就想到了递归,下面就一步一步的实现这个compose,首先,compose返回一个函数,为了记录递归的执行情况,还要记录参数的长度len,还要给返回的函数添加一个名字f1

var compose = function(...args) {
    var len = args.length
    return function f1() {

    }
}

函数体里面要做的事情就是不断的执行args中的函数,将上一个函数的执行结果作为下一个执行函数的输入参数,需要一个游标count来记录args函数列表的执行情况。

var compose = function(...args) {
    var len = args.length
    var count = len - 1
    var result
    return function f1(...args1) {
        result = args[count].apply(this, args1)
        count--
        return f1.call(null, result)
    }
}

这个就是思路,当然这样是不行的,没有退出条件,递归的退出条件就是最后一个函数执行完的时候,也就是count0的时候,这时候,有一点要注意,递归退出的时候,count游标一定要回归初始状态,最后补充一下代码

var compose = function(...args) {
        var len = args.length
        var count = len - 1
        var result
        return function f1(...args1) {
            result = args[count].apply(this, args1)
            if (count <= 0) {
                count = len - 1
                return result
            } else {
                count--
                return f1.call(null, result)
            }
        }
    }

这样就实现了这个compose函数。后来我发现递归这个完全可以使用迭代来实现,使用while函数看起来更容易明白,其实lodash.js就是这么实现的。

lodash实现

lodash的思路同上,不过是用迭代实现的,我就把它的源代码贴过来看一下

var flow = function(funcs) {
    var length = funcs.length
    var index = length
    while (index--) {
        if (typeof funcs[index] !== 'function') {
            throw new TypeError('Expected a function');
        }
    }
    return function(...args) {
        var index = 0
        var result = length ? funcs[index].apply(this, args) : args[0]
        while (++index < length) {
            result = funcs[index].call(this, result)
        }
        return result
    }
}
var flowRight = function(funcs) {
    return flow(funcs.reverse())
}

可以看出,lodash的本来实现是从左到右的,但也提供了从右到左flowRight,还多了一层函数的校验,而且接收的是数组,不是参数序列,而且从这行var result = length ? funcs[index].apply(this, args) : args[0]可以看出允许数组为空,可以看出还是非常严谨的。我写的就缺少这种严谨的异常处理。

结论

这次主要介绍了函数式编程中的compose函数的原理和实现方法,由于篇幅原因,我把打算分析的ramda.js源码实现放到下一篇来介绍,可以说ramda.js实现的compose更加函数式,需要单独好好分析。

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

热门AI工具

更多
DeepSeek
DeepSeek

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

豆包大模型
豆包大模型

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

通义千问
通义千问

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

腾讯元宝
腾讯元宝

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

文心一言
文心一言

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

讯飞写作
讯飞写作

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

即梦AI
即梦AI

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

ChatGPT
ChatGPT

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

相关专题

更多
java入门学习合集
java入门学习合集

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

2

2026.01.29

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

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

2

2026.01.29

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

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

0

2026.01.29

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

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

0

2026.01.29

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

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

3

2026.01.29

clawdbot ai使用教程 保姆级clawdbot部署安装手册
clawdbot ai使用教程 保姆级clawdbot部署安装手册

Clawdbot是一个“有灵魂”的AI助手,可以帮用户清空收件箱、发送电子邮件、管理日历、办理航班值机等等,并且可以接入用户常用的任何聊天APP,所有的操作均可通过WhatsApp、Telegram等平台完成,用户只需通过对话,就能操控设备自动执行各类任务。

25

2026.01.29

clawdbot龙虾机器人官网入口 clawdbot ai官方网站地址
clawdbot龙虾机器人官网入口 clawdbot ai官方网站地址

clawdbot龙虾机器人官网入口:https://clawd.bot/,clawdbot ai是一个“有灵魂”的AI助手,可以帮用户清空收件箱、发送电子邮件、管理日历、办理航班值机等等,并且可以接入用户常用的任何聊天APP,所有的操作均可通过WhatsApp、Telegram等平台完成,用户只需通过对话,就能操控设备自动执行各类任务。

16

2026.01.29

Golang 网络安全与加密实战
Golang 网络安全与加密实战

本专题系统讲解 Golang 在网络安全与加密技术中的应用,包括对称加密与非对称加密(AES、RSA)、哈希与数字签名、JWT身份认证、SSL/TLS 安全通信、常见网络攻击防范(如SQL注入、XSS、CSRF)及其防护措施。通过实战案例,帮助学习者掌握 如何使用 Go 语言保障网络通信的安全性,保护用户数据与隐私。

8

2026.01.29

俄罗斯Yandex引擎入口
俄罗斯Yandex引擎入口

2026年俄罗斯Yandex搜索引擎最新入口汇总,涵盖免登录、多语言支持、无广告视频播放及本地化服务等核心功能。阅读专题下面的文章了解更多详细内容。

622

2026.01.28

热门下载

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

相关下载

更多

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
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号