javascript技巧

关注公众号 jb51net

关闭
首页 > 网络编程 > JavaScript > javascript技巧 > JS纯函数、柯里化、组合函数

JS函数式编程之纯函数、柯里化以及组合函数

作者:虚幻私塾

这篇文章主要介绍了JS函数式编程之纯函数、柯里化以及组合函数,文章对三个函数进行分析讲解,内容也很容易理解,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下

前言

函数式编程(Functional Programming),又称为泛函编程,是一种编程范式。

早在很久以前就提出了函数式编程这个概念了,而后面一直长期被面向对象编程所统治着,最近几年函数式编程又回到了大家的视野中,JavaScript是一门以函数为第一公民的语言,必定是支持这一种编程范式的。

下面就来谈谈JavaScript函数式编程中的核心概念纯函数、柯里化以及组合函数。

纯函数

纯函数的概念

对于纯函数的定义,维基百科中是这样描述的:在程序设计中,若函数符合以下条件,那么这个函数被称之为纯函数。

对以上描述总结就是:

副作用

上面提到了一个词叫“副作用”,那么什么是副作用呢?

纯函数案例

function sum(a, b) {
 return a + b
}

const res = sum(10, 20)
console.log(res) // 30
let message = 'hello'
function sum(a, b) {
 message = 'hi'
 return a + b
}

1.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 ]

2.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 ]

柯里化

柯里化的概念

对于柯里化的定义,维基百科中是这样解释的:

总结:只传递给函数一部分参数来调用它,让它返回一个函数去处理剩余的参数的过程就称之为柯里化。

函数柯里化的过程

编写一个普通的三值求和函数:

function sum(x, y, z) {
 return x + y + z
}
const res = sum(10, 20, 30)
console.log(res) // 60

将以上求和函数柯里化得:

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

函数柯里化的特点及应用

1.将上面的三值求和函数增加一个需求,在计算结果之前给每个值加上2,先看看不使用柯里化的实现效果:

function sum(x, y, z) {
 x = x + 2
 y = y + 2
 z = z + 2
 return x + y + z
}

2.柯里化的实现效果:

function sum(x) {
 x = x + 2
 return function(y) {
 y = y + 2
 return function(z) {
 z = z + 2
 return x + y + z
 }
 }
}

3.很明显函数柯里化后,让我们对每个参数的处理更加单一

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

自动柯里化函数的实现

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

组合函数

**组合函数(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

到此这篇关于JS函数式编程之纯函数、柯里化以及组合函数的文章就介绍到这了,更多相关纯函数、柯里化、组合函数内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

您可能感兴趣的文章:
阅读全文