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

函数柯里化

文章目录

  • 基本概念
  • 柯里化(Currying)是什么?
  • 通用的柯里化实现
    • ES5 实现
    • ES6 实现


基本概念

在讲柯里化之前我们先来了解一些基本概念:

Function.length: length 属性指明函数的形参个数

function func1() {}
function func2(a, b) {}console.log(func1.length);  // 0
console.log(func2.length); // 2

Arguments 对象: 是一个对应于传递给函数的参数的类数组对象

  1. arguments 对象是所有(非箭头函数中都可用的局部变量
  2. “类数组”意味着 arguments 有长度属性,并且属性的索引是从零开始的,但是它没有 Array的内置方法,例如 forEach() 和 map()都是没有的
  3. arguments.length:本次函数调用时传入函数的实参数量(这个数字可以比形参数量大,也可以比形参数量小)
  4. arguments 可以被转换为一个真正的 Array
//  arguments 转换为一个真正的 Array
var args = Array.prototype.slice.call(arguments);
var args = [].slice.call(arguments);// ES6
const args = Array.from(arguments);
const args = [...arguments];

这里小提一下: How does Array.prototype.slice.call work?

.call()和.apply()方法允许您在函数中手动设置this的值。因此,如果我们将.slice()中的this的值设置为一个类似数组的对象,.slice()将假设它正在处理一个数组,并将执行它的任务。

剩余参数:允许我们将一个不定数量的参数表示为一个数组

如果函数的最后一个命名参数以…为前缀,则它将成为一个由剩余参数组成的真数组,其中从0(包括)到theArgs.length(排除)的元素由传递给函数的实际参数提供

function sum1(...theArgs) {console.log(theArgs)
}sum1(1, 2, 3); // [1, 2, 3]function sum2(a, ...theArgs) {console.log(theArgs)
}sum2(1, 2, 3); // [2, 3]

注:剩余参数只包含那些没有对应形参的实参,而 arguments 对象包含了传给函数的所有实参。

柯里化(Currying)是什么?

柯里化,是把接受多个参数的函数变换成接受一个单一参数(最初函数的第一个参数)的函数,并且返回接受余下的参数而且返回结果的新函数的技术。核心思想是把多参数传入的函数拆成单参数(或部分)函数,内部再返回调用下一个单参数(或部分)函数,依次处理剩余的参数。

举个例子:

// 传统写法
function sum(a, b, c) {return a + b + c
}
console.log(sum(1,2,3));  // 6// 柯里化
function sum(a) {return function (b) {return function (c) {return a + b + c}}
}
console.log(sum(1)(2)(3)); // 6// 将 a + b + c 的操作提取成一个方法
function curry(fn) {return function (a) {return function (b) {return function (c) {return fn(a, b, c);};};}
}function add(a, b, c) {return a + b + c;
}
var sum = curry(add);
console.log(sum(1)(2)(3)); // 6

这样就对一个函数实现了柯里化。但这个 curry 函数并不通用,实际开发过程中参数数量具有不确定性:比如 sum(1)(2,3) 或 sum(1,2)(3) ,或是一个函数需要传 n 个参数,如下:

function curry(fn) {return function (a1) {return function (a2) {return function (a3) {//......return function (aN) {return fn(a1, a2, a3, ...aN);};};};};
}

我们需要实现一个通用的柯里化函数,对于参数的不确定性,我们可以通过使用 arguments递归 来处理。

通用的柯里化实现

在下面实现代码中所用到的一些属性、对象、方法我们已在基本概念中介绍过,方便大家理解。

ES5 实现

// 法一  (递归调用 judge)
function curry(fn) {return function judge() {// arguments 转换为数组var _args = Array.prototype.slice.call(arguments);// 判断首次(或组合后)所传的参数数量 是否小于 fn 方法的形参个数if (_args.length < fn.length) {// 首次(或组合后)所传的参数数量 小于 fn 方法的形参个数, 内部再返回调用下一个单参数(或部分)函数return function (){// 获取当前参数数组var _args2 =  Array.prototype.slice.call(arguments);// 将之前所传的参数和当前的参数组合,递归调用return judge.apply(this, _args.concat(_args2))};} else {//  首次(或组合后)所传的参数数量 等于 fn 方法的形参个数,则直接调用 fn 函数return fn.apply(this, _args);}}
}// 法二 (递归调用 curry)
function curry(fn, args) {var args = args || []; // 首次为 []return function () {var _args = args.concat([].slice.call(arguments));if (_args.length < fn.length) {return curry.call(this, fn, _args);} else {return fn.apply(this, _args);}}
}function add(a, b ,c) {return a + b + c;
}const addCurry = curry(add);console.log(addCurry(1,2)(3)) // 6console.log(addCurry(1)(2)(3)) // 6console.log(addCurry(1)(2,3)) // 6

简而言之,就是将所有实际的传参组合起来,如果实际参数个数等于 fn 方法的形参个数后便调用 fn 方法。

ES6 实现

// 法一  (递归调用 judge)
const curry = (fn) => {return function judge(...args) {if (args.length < fn.length) {return function (...args2) {return judge(...args, ...args2);};}return fn(...args);};
}// 法二 (递归调用 curry)
const curry = (fn, ...arg) => (arg.length >= fn.length ? fn(...arg) : (..._arg) => curry(fn, ...arg, ..._arg))function add(a, b ,c) {return a + b + c;
}const addCurry = curry(add);console.log(addCurry(1,2)(3)) // 6console.log(addCurry(1)(2)(3)) // 6console.log(addCurry(1)(2,3)) // 6

想要明白柯里化函数,还是建议大家动手写写,在写的过程中分析执行步骤,方便理解。

相关文章:

函数柯里化

文章目录 基本概念柯里化&#xff08;Currying&#xff09;是什么&#xff1f;通用的柯里化实现ES5 实现ES6 实现 基本概念 在讲柯里化之前我们先来了解一些基本概念&#xff1a; Function.length&#xff1a; length 属性指明函数的形参个数 function func1() {} function …...

【HBZ分享】ES中的Reindex重建索引

Reindex如何实现索引重建&#xff1f; 滚动索引 批量复制 Reindex存在的问题 如果新的索引没有提前创建好&#xff0c;并指定字段类型&#xff0c;那么重建后的新索引类型极有可能会和旧的索引不一致&#xff0c;因为ES他会推断类型&#xff0c;而推断错误率从实战来说那是…...

【PostgreSQL】几个提高性能的小特性

一、LOCALE 与 “operator class” 在PostgreSQL里&#xff0c;LOCALE默认使用C的本地化规则。LOCALE是一种文化偏好的区域设置&#xff0c;包括字母表、排序、数字格式等。 LOCALE里有一个比较重要的规则LC_COLLATE&#xff0c;即排序方式(Collation)&#xff0c;它会对数据…...

[C语言] 指针

1. 指针是什么 2. 指针和指针类型 3. 野指针 4. 指针运算 5. 指针和数组 6. 二级指针 7. 指针数组 目录 1. 指针是什么&#xff1f; 2. 指针和指针类型 2.1 指针-整数 2.2 指针的解引用 3. 野指针 3.1 野指针成因 3.2 如何规避野指针 4. 指针运算 4.1 指针…...

win10在vmware15中安装macos10.13系统

第一步、安装vmware版本信息如下 第二步、下载unlocker-main和darwin.iso放到安装文件夹 第三步、管理员身份运行win-install.cmd 第四步、运行vmware新建虚拟机 第五步、启动新创建的虚拟机macOS 10.13并选择语言 第六步、选择磁盘工具抹掉磁盘 第七步、格式化完成后退出磁盘工…...

Node.js:实现遍历文件夹下所有文件

Node.js&#xff1a;实现遍历文件夹 代码如下 const fs require(fs) const path require(path)function traverseFolder(folderPath) {// 读取文件夹列表const files fs.readdirSync(folderPath)// 遍历文件夹列表files.forEach(function (fileName) {// 拼接当前文件路径…...

Git详解及使用

Git简介 Git 是一种分布式版本控制系统&#xff0c;它可以不受网络连接的限制&#xff0c;加上其它众多优点&#xff0c;目前已经成为程序开发人员做项目版本管理时的首选&#xff0c;非开发人员也可以用 Git 来做自己的文档版本管理工具。 大概是大二的时候开始接触和使用Gi…...

Jmeter设置中文的两种方式,建议使用第二种

方案一 进入jmeter图像化界面&#xff0c;选择Options下的Choose Language&#xff0c;再选择Chinese(Simplified)。这个就是选择语言为简体中文&#xff08;缺陷&#xff1a;这个只是在本次使用时为中文&#xff0c;下次打开默认还是英文的&#xff09; 方案二&#xff08;…...

【ARM 嵌入式 编译系列 7.1 -- GCC 链接脚本中节区及各个段的详细介绍】

文章目录 什么是Section(节区)输入文件常见节区有哪些&#xff1f;什么是 glue code&#xff1f;.glue_7和.glue_7的作用是什么&#xff1f;链接脚本中的 KEEP 关键字是什么呢作用&#xff1f;链接脚本中的 PROVIDE 关键字是什么呢作用&#xff1f; 上篇文章&#xff1a;ARM 嵌…...

一文读懂HTML

文章目录 HTML的历史HTML的作用HTML的基本语言 HTML的历史 HTML&#xff08;HyperText Markup Language&#xff09;的历史可以追溯到20世纪90年代早期&#xff0c;它是互联网发展的重要里程碑之一。以下是HTML的历史概述&#xff1a; 早期阶段&#xff08;1980年代末 - 1990年…...

MOCK测试

介绍 mock&#xff1a;就是对于一些难以构造的对象&#xff0c;使用虚拟的技术来实现测试的过程。 mock测试&#xff1a;在测试过程中&#xff0c;对于某些不容易构造或者不容易获取的对象&#xff0c;可以用一个虚拟的对象来代替的测试方 法。 接口Mock测试&#xff1a;在接口…...

Flutter源码分析笔记:Widget类源码分析

Flutter源码分析笔记 Widget类源码分析 - 文章信息 - Author: 李俊才 (jcLee95) Visit me at: https://jclee95.blog.csdn.netEmail: 291148484163.com. Shenzhen ChinaAddress of this article:https://blog.csdn.net/qq_28550263/article/details/132259681 【介绍】&#x…...

PyTorch 微调终极指南:第 2 部分 — 提高模型准确性

一、说明 如今&#xff0c;在训练深度学习模型时&#xff0c;通过在自己的数据上微调预训练模型来迁移学习已成为首选方法。通过微调这些模型&#xff0c;我们可以利用他们的专业知识并使其适应我们的特定任务&#xff0c;从而节省宝贵的时间和计算资源。本文分为四个部分&…...

MySQL数据库----------安装anaconda---------python与数据库的链接

作者前言 &#x1f382; ✨✨✨✨✨✨&#x1f367;&#x1f367;&#x1f367;&#x1f367;&#x1f367;&#x1f367;&#x1f367;&#x1f382; ​&#x1f382; 作者介绍&#xff1a; &#x1f382;&#x1f382; &#x1f382; &#x1f389;&#x1f389;&#x1f389…...

nuxt页面布局

nuxt页面默认布局文件在layouts目录下default.vue&#xff0c;可将页面的头部和脚部提取出来&#xff0c;形成布局页&#xff0c;将主内容区域的内容替换成<nuxt />。附default.vue代码&#xff1a; <template><div class"app-container"><div…...

mac编译ffmpeg

- code&#xff1a; git clone https://git.ffmpeg.org/gitweb/ffmpeg.git - 编译安装 https://trac.ffmpeg.org/wiki/CompilationGuide - 使用homebrew安装dependency brew install automake fdk-aac git lame libass libtool libvorbis libvpx \ opus sdl shtool texi2ht…...

如何让你的图片服务也有类似OSS的图片处理功能

原文链接 前言 有自己机房的公司一般都有一套存储系统用于存储公司的图片、视频、音频、文件等数据&#xff0c;常见的存储系统有以NAS、FASTDFS为代表的传统文件存储&#xff0c;和以Minio为代表的对象存储系统&#xff0c;随着云服务的兴起很多公司逐渐将数据迁移到以阿里云…...

Oracle PL/SQL 类型(Type):索引表、嵌套表、变长数组、pipelined 管道

1、Oracle 新建员工表和部门表.sql。 集合类型 1、Oracle 集合是相同类型元素的组合&#xff0c;在集合中&#xff0c;使用唯一的下标来标识其中的每个元素&#xff0c;与 Java 的 List 很像。 2、常用集合方式&#xff1a; 类型语法下标元素个数初始值.extend能否存在DB中…...

Web 服务器 -【Tomcat】的简单学习

Tomcat1 简介1.1 什么是Web服务器 2 基本使用2.1 下载2.2 安装2.3 卸载2.4 启动2.5 关闭2.6 配置2.7 部署 3 Maven创建Web项目3.1 Web项目结构3.2 创建Maven Web项目 4 IDEA使用Tomcat4.1 集成本地Tomcat4.2 Tomcat Maven插件 Tomcat 1 简介 1.1 什么是Web服务器 Web服务器是…...

armbian使用1panel快速部署部署springBoot项目后端

文章目录 前言环境准备实现步骤第一步&#xff1a;Armbian安装1panel第二步&#xff1a;安装数据库第三步&#xff1a;查看数据库容器重要信息【重要】查看容器所在的网络查看容器连接地址 第四步&#xff1a;项目配置和打包第五步:构建项目镜像 前言 这里只是简单记录部署spr…...

脑机新手指南(八):OpenBCI_GUI:从环境搭建到数据可视化(下)

一、数据处理与分析实战 &#xff08;一&#xff09;实时滤波与参数调整 基础滤波操作 60Hz 工频滤波&#xff1a;勾选界面右侧 “60Hz” 复选框&#xff0c;可有效抑制电网干扰&#xff08;适用于北美地区&#xff0c;欧洲用户可调整为 50Hz&#xff09;。 平滑处理&…...

【人工智能】神经网络的优化器optimizer(二):Adagrad自适应学习率优化器

一.自适应梯度算法Adagrad概述 Adagrad&#xff08;Adaptive Gradient Algorithm&#xff09;是一种自适应学习率的优化算法&#xff0c;由Duchi等人在2011年提出。其核心思想是针对不同参数自动调整学习率&#xff0c;适合处理稀疏数据和不同参数梯度差异较大的场景。Adagrad通…...

Java多线程实现之Callable接口深度解析

Java多线程实现之Callable接口深度解析 一、Callable接口概述1.1 接口定义1.2 与Runnable接口的对比1.3 Future接口与FutureTask类 二、Callable接口的基本使用方法2.1 传统方式实现Callable接口2.2 使用Lambda表达式简化Callable实现2.3 使用FutureTask类执行Callable任务 三、…...

Linux云原生安全:零信任架构与机密计算

Linux云原生安全&#xff1a;零信任架构与机密计算 构建坚不可摧的云原生防御体系 引言&#xff1a;云原生安全的范式革命 随着云原生技术的普及&#xff0c;安全边界正在从传统的网络边界向工作负载内部转移。Gartner预测&#xff0c;到2025年&#xff0c;零信任架构将成为超…...

【OSG学习笔记】Day 16: 骨骼动画与蒙皮(osgAnimation)

骨骼动画基础 骨骼动画是 3D 计算机图形中常用的技术&#xff0c;它通过以下两个主要组件实现角色动画。 骨骼系统 (Skeleton)&#xff1a;由层级结构的骨头组成&#xff0c;类似于人体骨骼蒙皮 (Mesh Skinning)&#xff1a;将模型网格顶点绑定到骨骼上&#xff0c;使骨骼移动…...

Java线上CPU飙高问题排查全指南

一、引言 在Java应用的线上运行环境中&#xff0c;CPU飙高是一个常见且棘手的性能问题。当系统出现CPU飙高时&#xff0c;通常会导致应用响应缓慢&#xff0c;甚至服务不可用&#xff0c;严重影响用户体验和业务运行。因此&#xff0c;掌握一套科学有效的CPU飙高问题排查方法&…...

【Post-process】【VBA】ETABS VBA FrameObj.GetNameList and write to EXCEL

ETABS API实战:导出框架元素数据到Excel 在结构工程师的日常工作中,经常需要从ETABS模型中提取框架元素信息进行后续分析。手动复制粘贴不仅耗时,还容易出错。今天我们来用简单的VBA代码实现自动化导出。 🎯 我们要实现什么? 一键点击,就能将ETABS中所有框架元素的基…...

智能职业发展系统:AI驱动的职业规划平台技术解析

智能职业发展系统&#xff1a;AI驱动的职业规划平台技术解析 引言&#xff1a;数字时代的职业革命 在当今瞬息万变的就业市场中&#xff0c;传统的职业规划方法已无法满足个人和企业的需求。据统计&#xff0c;全球每年有超过2亿人面临职业转型困境&#xff0c;而企业也因此遭…...

ArcPy扩展模块的使用(3)

管理工程项目 arcpy.mp模块允许用户管理布局、地图、报表、文件夹连接、视图等工程项目。例如&#xff0c;可以更新、修复或替换图层数据源&#xff0c;修改图层的符号系统&#xff0c;甚至自动在线执行共享要托管在组织中的工程项。 以下代码展示了如何更新图层的数据源&…...

LangChain【6】之输出解析器:结构化LLM响应的关键工具

文章目录 一 LangChain输出解析器概述1.1 什么是输出解析器&#xff1f;1.2 主要功能与工作原理1.3 常用解析器类型 二 主要输出解析器类型2.1 Pydantic/Json输出解析器2.2 结构化输出解析器2.3 列表解析器2.4 日期解析器2.5 Json输出解析器2.6 xml输出解析器 三 高级使用技巧3…...