纯函数、柯里化、组合函数


theme: smartblue

highlight: a11y-dark

一、纯函数

1、概念

1)此函数在相同的输入值时,需产生相同的输出;

image-20220918235054033

2)函数的输出和输入值以外的其他隐藏信息或状态无关,也和由I/O设备产生的外部输出无关;

3)该函数不能有语义上可观察的函数副作用,如“触发事件”,使输出设备输出,或更改输出值以外物件的内容等;

4)确定输入,一定会产生确定的输出;

5)函数执行过程中,不能产生任何副作用;

注:在计算机科学中,副作用的概念,表示在执行一个函数时,除了返回函数值之外,还对调用函数产生 了附加的影响,比如修改了全局变量,修改参数或者改变外部的存储。

image-20221106000254447

2、纯函数理解

1、判断是否时一个纯函数

```javascript let obj = {name: '小明', age: 10}

/** * 判断下面两个那个时纯函数? * fun 不是 * test 是 */ // fun 会修改 obj 对象的本身 function fun(info){ info.age = 100 } fun(obj)

// test 不会修改对象本身,并且 会返回一个新的对象 // 当你给 test 中传入相同的对象时,他的返回值也是相同的,这就符合纯函数的定义 function test(info){ return { ...info, age: info.age + 1 } } test(obj) test(obj) ```

注:在开发过程中,使用非纯函数,他往往就会成为 bug 的温床。

二、柯里化

给函数传递一部分参数来调用这个函数,并且 当前的这个函数他会在返回一个函数,去处理剩余的参数,见下面 示例:

202211270030133

也就是 拆分函数的参数,这样的就可以叫 柯里化

1、使用函数柯里化的好处?

​ 在函数式的编程中,尽量 让一个函数处理一个问题,尽可能的单一,而不是将一些问题交给一个方法去解决,就好比 react 的函数式组件,你的一个功能组件是经过多个 UI 组件合成而来的一样,所以我们可以将每次传入的参数在,当前函数中处理,在当前函数处理完成后,在下一个函数中在使用上一个函数的处理结果即可。

2、例子

实现一个给第一个参数加2,给第二个参数乘2的例子

image-20221119234210286

3、柯里化函数的实现

注:也就是把多个参数的函数转换成柯里化函数,这是一个可以作为公共方法的函数。

```javascript /** * 多参函数 转 柯里化函数 */ function currying(fn) { // 接受一个函数,返回一个函数 // 这里是接受剩余参数 function receivedParameters(...args) { // 判断当前已经接受到的参数的个数, 和参数本身(这个参数本身就是一个函数)需要接收到参数是否已经一致 // console.log(fn.length); // console.log(args.length); // 到传入函数的参数(fn 的参数) 大于 传入的参数(...args)时,就直接调用传入的函数 if (args.length >= fn.length) { // 这个 apply 是为了方式外面调用时,绑定了this,而导致这个里面执行 fn 时的混乱 return fn.apply(this, args); } else { // 当参数不够的时候, 需要返回一个函数,来接续接收传入的参数,所以 在这 就需要把传入的所有参数,进行一次拼接 return function (...smallArgs) { // 这个里面用了递归,来检查参数 是否达到,达到了,就运行传入的函数(fn) return receivedParameters.apply(this, [...args, ...smallArgs]) } } } return receivedParameters }

// 使用 function fun(n, m, b) { // fun的参数个数,是可以 通过 fun.length 拿到的 return n + m + b }

const test = currying(fun);

console.log(test(1, 2, 3)); console.log(test(1)(2, 3)) console.log(test(1)(2)(3)); ```

三、组合函数

当要获取的结果,是多个纯函数共同运算获得的,这个时候就可以那这几个陈函数组合起来,一次进行调用,这就叫组合函数,它可以减少代码的冗余。

```javascript function add(num){ return num + 10 }

function multiply(num){ return num * 2 }

const num = add(multiply(2)); console.log(num);

// 下面开始组合上面的两个函数 function composeFn(fn1, fn2){ return function(props){ return fn1(fn2(props)) } }

const newFn = composeFn(add, multiply); console.log(newFn(2)); ```

使用:

``javascript /** * 组合函数 * @param {...any} fns 函数 */ function composeFn(...fns){ for(let i = 0; i < fns.length; i++){ if(typeof fns[i] !== 'function'){ throw new TypeError(${fns[i]} 不是函数类型`); } } /** * 参数 * 下面的难点 是 apply 、call 的使用 */ return function(...args){ let index = 0; // 从零开始 let result = fns.length ? fns[index].apply(this, args) : args; // 判断是否有函数参数传入 while(++index < fns.length){ result = fns[index].call(this, result); } return result; } }

function add1(num){ return num + 10 } function add2(num){ return num + 1 } console.log(add2(add1(1))); // 原始的使用

const test = composeFn(add1, add2); console.log(test(1)); ```

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值