JavaScript函数式编程(纯函数、柯里化以及组合函数)
JavaScript函数式编程(纯函数、柯里化以及组合函数)
目录
- JavaScript函数式编程(纯函数、柯里化以及组合函数)
- 前言
- 1.纯函数
- 1.1.纯函数的概念
- 1.2.副作用
- 1.3.纯函数案例
- 2.柯里化
- 2.1.柯里化的概念
- 2.2.函数柯里化的过程
- 2.3.函数柯里化的特点及应用
- 2.4.自动柯里化函数的实现
- 3.组合函数
前言
函数式编程(Functional Programming),又称为泛函编程,是一种编程范式。早在很久以前就提出了函数式编程这个概念了,而后面一直长期被面向对象编程所统治着,最近几年函数式编程又回到了大家的视野中,JavaScript是一门以函数为第一公民的语言,必定是支持这一种编程范式的,下面就来谈谈JavaScript函数式编程中的核心概念纯函数、柯里化以及组合函数。
1.纯函数
1.1.纯函数的概念
对于纯函数的定义,维基百科中是这样描述的:在程序设计中,若函数符合以下条件,那么这个函数被称之为纯函数。
- 此函数在相同的输入值时,需产生相同的输出;
- 函数的输入和输出值以外的其他隐藏信息或状态无关,也和由I/O设备产生的外部输出无关;
- 该函数不能有语义上可观察的函数副作用,诸如“触发事件”,使输出设备输出,或更改输出值以外物件的内容等;
对以上描述总结就是:
- 对于相同的输入,永远会得到相同的输出;
- 在函数的执行过程中,没有任何可观察的副作用;
- 同时也不依赖外部环境的状态;
1.2.副作用
上面提到了一个词叫“副作用”,那么什么是副作用呢?
- 通常我们所说的副作用大多数是指药会产生的副作用;
- 而在计算机科学中,副作用指在执行一个函数时,除了得到函数的返回值以外,还在函数调用时产生了附加的影响,比如修改了全局变量的状态,修改了传入的参数或得到了其它的输出内容等;
1.3.纯函数案例
编写一个求和的函数sum,只要我们输入了固定的值,sum函数就会给我们返回固定的结果,且不会产生任何副作用。
function sum(a, b) {return a + b }const res = sum(10, 20) console.log(res) // 30
以下的sum函数虽然对于固定的输入也会返回固定的输出,但是函数内部修改了全局变量message,就认定为产生了副作用,不属于纯函数。
let message = 'hello' function sum(a, b) {message = 'hi'return a + b }
在JavaScript中也提供了许多的内置方法,有些是纯函数,有些则不是。像操作数组的两个方法slice和splice。
slice方法就是一个纯函数,因为对于同一个数组固定的输入可以得到固定的输出,且没有任何副作用;
const nums = [1, 2, 3, 4, 5] const newNums = nums.slice(1, 3) console.log(newNums) // [2, 3] console.log(nums) // [ 1, 2, 3, 4, 5 ]
splice方法不是一个纯函数,因为它改变了原数组nums;
const nums = [1, 2, 3, 4, 5] const newNums = nums.splice(1, 3) console.log(newNums) // [ 2, 3, 4 ] console.log(nums) // [ 1, 5 ]
2.柯里化
2.1.柯里化的概念
对于柯里化的定义,维基百科中是这样解释的:
- 柯里化是指把接收多个参数的函数,变成接收一个单一参数(最初函数的第一个参数)的函数,并且返回接收余下的参数,而且返回结果的新函数的技术;
- 柯里化声称**“如果你固定某些参数,你将得到接受余下参数的一个函数”**;
总结:只传递给函数一部分参数来调用它,让它返回一个函数去处理剩余的参数的过程就称之为柯里化。
2.2.函数柯里化的过程
编写一个普通的三值求和函数:
function sum(x, y, z) {return x + y + z
}const res = sum(10, 20, 30)
console.log(res) // 60
将以上求和函数柯里化得:
- 将传入的三个参数进行拆解,依次返回一个函数,并传入一个参数;
- 在保证同样功能的同时,其调用方式却发生了变化;
- 注意:在拆解参数时,不一定非要将参数拆成一个个的,也可以拆成2+1或1+2;
function sum(x) {return function(y) {return function(z) {return x + y + z}}
}const res = sum(10)(20)(30)
console.log(res)
使用ES6箭头函数简写为:
const sum = x => y => z => x + y + z
2.3.函数柯里化的特点及应用
**让函数的职责更加单一。**柯里化可以实现让一个函数处理的问题尽可能的单一,而不是将一大堆逻辑交给一个函数来处理。
将上面的三值求和函数增加一个需求,在计算结果之前给每个值加上2,先看看不使用柯里化的实现效果:
function sum(x, y, z) {x = x + 2y = y + 2z = z + 2return x + y + z }
柯里化的实现效果:
function sum(x) {x = x + 2return function(y) {y = y + 2return function(z) {z = z + 2return x + y + z}} }
很明显函数柯里化后,让我们对每个参数的处理更加单一
**提高函数参数逻辑复用。**同样使用上面的求和函数,增加另一个需求,固定第一个参数的值为10,直接看柯里化的实现效果吧,后续函数调用时第一个参数值都为10的话,就可以直接调用sum10函数了。
function sum(x) {return function(y) {return function(z) {return x + y + z}} }const sum10 = sum(10) // 指定第一个参数值为10的函数 const res = sum10(20)(30) console.log(res) // 60
2.4.自动柯里化函数的实现
function autoCurrying(fn) {// 1.拿到当前需要柯里化函数的参数个数const fnLen = fn.length// 2.定义一个柯里化之后的函数function curried_1(...args1) {// 2.1拿到当前传入参数的个数const argsLen = args1.length// 2.1.将当前传入参数个数和fn需要的参数个数进行比较if (argsLen >= fnLen) {// 如果当前传入的参数个数已经大于等于fn需要的参数个数// 直接执行fn,并在执行时绑定this,并将对应的参数数组传入return fn.apply(this, args1)} else {// 如果传入的参数不够,说明需要继续返回函数来接收参数function curried_2(...args2) {// 将参数进行合并,递归调用curried_1,直到参数达到fn需要的参数个数return curried_1.apply(this, [...args1, ...args2])}// 返回继续接收参数函数return curried_2}}// 3.将柯里化的函数返回return curried_1
}
测试:
function sum(x, y, z) {return x + y + z
}const curryingSum = autoCurrying(sum)const res1 = curryingSum(10)(20)(30)
const res2 = curryingSum(10, 20)(30)
const res3 = curryingSum(10)(20, 30)
const res4 = curryingSum(10, 20, 30)
console.log(res1) // 60
console.log(res2) // 60
console.log(res3) // 60
console.log(res4) // 60
3.组合函数
**组合函数(Compose Function)**是在JavaScript开发过程中一种对函数的使用技巧、模式。对某一个数据进行函数调用,执行两个函数,这两个函数需要依次执行,所以需要将这两个函数组合起来,自动依次调用,而这个过程就叫做函数的组合,组合形成的函数就叫做组合函数。
需求:对一个数字先进行乘法运算,再进行平方运算。
一般情况下,需要先定义两个函数,然后再对其依次调用:
function double(num) {return num * 2 } function square(num) {return num ** 2 }const duobleResult = double(10) const squareResult = square(duobleResult) console.log(squareResult) // 400
实现一个组合函数,将duoble和square两个函数组合起来:
function composeFn(fn1, fn2) {return function(num) {return fn2(fn1(num))} }const execFn = composeFn(double, square) const res = execFn(10) console.log(res) // 400
实现一个自动组合函数的函数:
function autoComposeFn(...fns) {// 1.拿到需要组合的函数个数const fnsLen = fns.length// 2.对传入的函数进行边界判断,所有参数必须为函数for (let i = 0; i < fnsLen; i++) {if (typeof fns[i] !== 'function') {throw TypeError('The argument passed must be a function.')}}// 3.定义一个组合之后的函数function composeFn(...args) {// 3.1.拿到第一个函数的返回值let result = fns[0].apply(this, args)// 3.1.判断传入的函数个数if (fnsLen === 1) {// 如果传入的函数个数为一个,直接将结果返回return result} else {// 如果传入的函数个数 >= 2// 依次将函数取出进行调用,将上一个函数的返回值作为参数传给下一个函数// 从第二个函数开始遍历for (let i = 1; i < fnsLen; i++) {result = fns[i].call(this, result)}// 将结果返回return result}}// 4.将组合之后的函数返回return composeFn
}
测试:
function double(num) {return num * 2
}
function square(num) {return num ** 2
}const composeFn = autoComposeFn(double, square)
const res = composeFn(10)
console.log(res) // 400
JavaScript函数式编程(纯函数、柯里化以及组合函数)相关推荐
- 纯函数、柯里化、组合函数的解析以及代码实现
文章目录 一.纯函数的概念和理解 二.JavaScript柯里化 1.柯里化的理解 2.将函数柯里化的代码实现 三.组合函数 1.组合函数的理解 2.通用的组合函数的实现 一.纯函数的概念和理解 纯函 ...
- JS函数式编程思维:柯里化、闭包
偏函数(Partial Application): 探讨柯里化之前,我们先聊一聊很容易跟其混淆的另一个概念--偏函数(Partial Application).在维基百科中,对 Partial App ...
- 从一道面试题认识函数柯里化
最近在整理面试资源的时候,发现一道有意思的题目,所以就记录下来. 题目 如何实现 multi(2)(3)(4)=24? 首先来分析下这道题,实现一个 multi 函数并依次传入参数执行,得到最终的结果 ...
- scala 环境搭建 变量 值 数据类型 元组 表达式块 语句 函数 柯里化 集合 面向对象 隐式转换
scala (scalable的简写) scala是一个比较冷门的语言,不太被人们所知道 为什么这么冷门的语言现在被我们使用 很多的大数据的项目的源码是是用scala语言编写的. 因为大数据技术不断被 ...
- 了解js基础知识中的作用域和闭包以及闭包的一些应用场景,浅析函数柯里化
js基础知识中的作用域和闭包 一.作用域 1.作用域.自由变量简介 (1)作用域定义 (2)作用域实例演示 (3)自由变量定义 (4)自由变量实例演示 2.作用域链简介 (1)作用域链定义 (2)作用 ...
- 什么是函数柯里化,函数柯里化的应用场景,函数柯里化的优缺点
函数柯里化 1. 什么是函数柯里化? 2. 函数柯里化面试题 3. 应用场景 1. 什么是函数柯里化? 函数柯里化是js闭包的典型应用.所以缺点就是闭包造成的缺点,占用内存较多等 什么是函数柯里化?就 ...
- 带你看懂javascript函数柯里化(currying)
1.什么是柯里化 这里参照百度百科: 在计算机科学中,柯里化(Currying)是把接受多个参数的函数变换成接受一个单一参数(最初函数的第一个参数)的函数,并且返回接受余下的参数且返回结果的新函数的技 ...
- JavaScript 专题之函数柯里化
JavaScript 专题系列第十三篇,讲解函数柯里化以及如何实现一个 curry 函数 定义 维基百科中对柯里化 (Currying) 的定义为: In mathematics and comput ...
- [转载] 纯函数和函数柯里化
参考链接: 用示例编写Java柯里化Currying函数 文章目录 纯函数什么是纯函数纯函数例子非纯函数例子 函数柯里化函数柯里化简单例子参数复用 纯函数 什么是纯函数 如果函数的调用参数相同,则永远 ...
最新文章
- mxnet与pytorch比较 bn层
- Android上常见度量单位【xdpi、hdpi、mdpi、ldpi】解读
- void类型和void *的用法
- 物流机器人小车的运动控制与定位
- 第1次在Flash Builder中写程序
- FreeBSD下使用Blogbio写cnblogs博客
- android谷歌打印插件下载地址,谷歌浏览器打印插件:Print Plus
- 简单的在线出入库管理用哪个系统好
- Windows 下取消活动分区的方法
- 根据银行卡号查询银行卡名称
- 腾讯云乐固客户端加固打包上线流程
- 黑帽实战 | 给大家讲讲一个二类电商的大佬的故事!
- 英文文献阅读时,如何做笔记?
- HTML字体以及图标字体iconfont、Font Awesome的使用
- mysql编码转换搞定
- Xcalibur的安装及使用说明-低分辨质谱仪采集的数据
- 8051写一个考研/雅思用的小计时器
- Markdown换行操作
- Paddle实践:手写数字识别
- Hive CTE与子查询
热门文章
- Java:判断是否是闰年
- [附源码]java+ssm计算机毕业设计基于ssm的二手手机商城rk2i3(源码+程序+数据库+部署)
- 群发邮件邮箱哪个群发数量高?群发邮件怎么发送更高效?
- 双十一电竞趴,4AM联手三星玄龙骑士掀起购物狂欢
- excel使用vb统计分数_使用Excel选项按钮计算调查分数
- 中海达ihand30手簿使用说明_GPS手簿 iHand30
- JavaWeb数据交互前后台[Java+JSP+MySql+tomcat] 仿12306购票系统前台和后台(一)项目介绍以及需求分析
- java并发怎么理解_java并发的理解
- android仿微博头像_Android 自定义 View 集锦|自定义圆形旋转进度条,仿微博头像加载效果...
- i7-1065G7和i5-1035G1 对比哪个好