当前位置: 首页 > news >正文

猿创征文 | JavaScript函数柯里化

目录

一、函数柯里化是什么?

二、如何实现函数柯里化?

1、第一种方法:多层return嵌套

2、第二种方法:将普通函数转成柯里化函数


一、函数柯里化是什么?

百度百科中对函数柯里化的解释是:在计算机科学中,柯里化(Currying)是把接受多个参数的函数变换成接受一个单一参数(最初函数的第一个参数)的函数,并且返回接受余下的参数且返回结果的新函数的技术。

举个🌰说明一下:

比如我们需要求三个数的和,我们一般的做法就是一次性传入三个参数进行求和:

function add(a, b, c){
      return a + b + c
}
//我们一般调用函数的方式
add(1, 2, 3)

而函数柯里化就是每次传入单一的参数,如下所示:

add(1)(2)(3)

那么,此时add函数应该如何写呢?

二、如何实现函数柯里化?

1、第一种方法:多层return嵌套

我们使用add(1)(2)(3)的方式调用函数,就需要每次都返回一个函数,add(1)(2)(3)就相当于:

var fn1 = add(1)
var fn2 = fn1(2)
fn2(3)

因此add函数可以这样写:

<script>
    function add(a){
      return function(b) {
        return function(c) {
          return a + b + c
        }
      }
    }
    console.log(add(1)(2)(3)); //6
</script>

这里使用到了闭包的原理来实现add函数,这种方法比较简单,很容易就能想到,但是这种方法并不通用,所以我们可以封装一个函数,用于将普通函数转成柯里化函数。

2、第二种方法:将普通函数转成柯里化函数

柯里化函数执行的过程就是一个收集参数的过程,因此我们只要收集完所有参数,然后把参数传递给普通函数执行即可。

<script>
    function add(a, b, c) {
      return a + b + c
    }

    function curry(fun, args) {
      //获取fun函数的形参个数
      var len = fun.length
      var args = args || []
      return function () {
        //arguments是实参列表,是一个类数组对象,使用slice方法可以将它转成数组
        //收集本次的参数
        var arrArgs = Array.prototype.slice.call(arguments)
        //拼接前面收集到的参数
        arrArgs = arrArgs.concat(args)
        //如果实参个数小于形参个数,说明参数还没有收集完,使用递归继续收集
        if (arrArgs.length < len) {
          return curry.call(this, fun, arrArgs)
        }
        //收集完了,则执行fun函数
        //1.使用apply
        return fun.apply(this, arrArgs)
        //2.使用call
        // return fun.call(this, ...arrArgs)
        //3.使用bind
        // return fun.bind(null, ...arrArgs)()
      }
    }
    //将add函数转成柯里化函数
    var addCurry = curry(add)
    //每次可以传递任意个参数
    console.log(addCurry(1)(2)(3)); //6
    console.log(addCurry(1, 2)(3)); //6
    console.log(addCurry(1)(2, 3)); //6
    console.log(addCurry(1, 2, 3)); //6
</script>

相关文章:

  • Servlet的注册和生命周期
  • [Latex] \bibitem{} | .bbl 格式参考文献转换与获得
  • cmake和makefile区别和cmake指定编译器(cmake -G)
  • JavaWeb对于Listener的运用详解【利用Session统计在线人数】
  • Windows命令: net与sc的区别
  • 向量数据库是如何检索的?基于 Feder 的 HNSW 可视化实现
  • 架构师的 36 项修炼第11讲:致未来的架构师
  • 基于springboot+vue的商城系统(电商平台)
  • Linux CentOS 8(用户组的管理实验)
  • .net core开源商城系统源码,支持可视化布局小程序
  • ElasticSearch诞生
  • DRM系列(7)之drmModeAtomicCommit底层流程
  • R语言ggplot2可视化:使用ggpubr包的ggline函数可视化折线图(点线图、line plot)
  • PHP FTP 函数
  • PHP Filter 函数
  • 2019年如何成为全栈工程师?
  • 30秒的PHP代码片段(1)数组 - Array
  • 345-反转字符串中的元音字母
  • css布局,左右固定中间自适应实现
  • flutter的key在widget list的作用以及必要性
  • JAVA_NIO系列——Channel和Buffer详解
  • LeetCode29.两数相除 JavaScript
  • PHP CLI应用的调试原理
  • python学习笔记 - ThreadLocal
  • Quartz实现数据同步 | 从0开始构建SpringCloud微服务(3)
  • React Native移动开发实战-3-实现页面间的数据传递
  • Spark in action on Kubernetes - Playground搭建与架构浅析
  • SpiderData 2019年2月25日 DApp数据排行榜
  • uva 10370 Above Average
  • 阿里云购买磁盘后挂载
  • 闭包--闭包作用之保存(一)
  • 表单中readonly的input等标签,禁止光标进入(focus)的几种方式
  • 多线程事务回滚
  • 构造函数(constructor)与原型链(prototype)关系
  • 聊一聊前端的监控
  • 时间复杂度与空间复杂度分析
  • 使用agvtool更改app version/build
  • 物联网链路协议
  • 消息队列系列二(IOT中消息队列的应用)
  • 学习JavaScript数据结构与算法 — 树
  • 译米田引理
  • 在electron中实现跨域请求,无需更改服务器端设置
  • 看到一个关于网页设计的文章分享过来!大家看看!
  • 阿里云ACE认证学习知识点梳理
  • ​批处理文件中的errorlevel用法
  • $ git push -u origin master 推送到远程库出错
  • (1)(1.9) MSP (version 4.2)
  • (WSI分类)WSI分类文献小综述 2024
  • (六)c52学习之旅-独立按键
  • (转贴)用VML开发工作流设计器 UCML.NET工作流管理系统
  • .Net core 6.0 升8.0
  • @Transactional 竟也能解决分布式事务?
  • [ C++ ] STL---stack与queue
  • [android] 看博客学习hashCode()和equals()
  • [Angular] 笔记 7:模块