函数柯里化

柯里化

定义

柯里化currying是一种函数的高阶技术,用于转换函数,将函数从f(a,b,c)转换为f(a)(b)(c)或者f(a,b)(c)或者f(a)(b,c)

柯里化不会调用函数,只是对函数进行转换。

柯里化也可以理解为部分求值,接收部分参数后,不会立即求值,而是返回一个接受剩余参数的函数。可以缩小函数的适用范围,创建一个针对性更强的函数,又称为偏应用型函数。

假设有一个求和的函数sum,设计一个curry函数使其柯里化。

r 复制代码
const sum = function(a,b,c){
    return a+b+c;
}

调用柯里化的函数满足以下结果:

scss 复制代码
sum(1,2,3) // 6
sum(1)(2,3) // 6
sum(1,2)(3) // 6
sum(1)(2)(3) // 6

根据柯里化暂存参数返回一个新偏函数的特点来设计柯里化辅助函数curry:

javascript 复制代码
const currySum = function(fn){
    return function(a){
        return function(b){
            return function(c){
                return sum(a,b,c);
             }
        }
    }
}
const newSum = currySum(sum);
console.log(newSum(1)(2)(3)); // 6

目前设计的curry函数只能满足f(a)(b)(c)形式的调用,其他形式的调用会报错。而且curry函数内部有多层函数嵌套的回调函数,造成代码的重复和难以维护。

柯里化有更高级的实现,例如 lodash 库的_.curry,其会返回一个包装器,该包装器允许函数被正常调用或者以任何偏函数的方式调用。

通用公式

函数柯里化又分为固定参数和任意参数。

  1. 固定参数个数,原函数参数确定
scss 复制代码
function myCurry(fn){
    return function curried(...args){
        if(args.length >= fn.length){
            return fn.apply(this,args);
        }else{
            return function(...args2){
                return curried.apply(this,args.concat(args2));
            }
        }
    }
}

const newSum1 = myCurry(sum);
console.log(newSum1(1,2,3)); // 6
console.log(newSum1(1)(2)(3)); // 6
console.log(newSum1(1,2)(3)); // 6
console.log(newSum1(1)(2,3)); // 6
  1. 任意参数个数,原函数参数长度不确定
ini 复制代码
const add = (...args) => {
    let vars = args;
    const curried = (...args) => {
        vars = [...vars, ...args];
        return curried;
    };
    curried.toString = () => {
        return vars.reduce((a, b) => a + b, 0);
    };
    return curried;
};

const res = add(1); // 1
const res = add(1,2,3); // 6
const res = add(1)(2)(3); // 6
const res = add(1)(2,3)(4)(5); // 15

console.log(res.toString(),'res是一个函数,需要调用其toString方法获取值');

优缺点

柯里化函数的优点:

  • 灵活性:将多个参数的函数转换成一系列只接受单个参数的函数,可以灵活地组合和使用函数

  • 可复用性:将柯里化函数的一部分参数预设,从而得到新的函数,该函数可以直接使用,也可以作为其他函数的参数使用

柯里化函数的缺点:

  • 可读性:原函数的调用变得更复杂,需要多次调用不同的函数才能得到最终结果,降低了代码的可读性

适应场景

  • 缩小函数适用范围:当函数需要传递一部分参数时,可以使用柯里化函数将该部分参数预设,从而得到新的函数

  • 参数复用:将一部分参数固化,反复使用

  • 延迟执行函数

scss 复制代码
const curryAdd = function(...rest){
    const args = rest;
    return function cb(...rest) {
        if (rest.length === 0) {
            return args.reduce((a, b) => a + b, 0);
        } else {
            args.push(...rest);
            return cb;
        }
    };
}()

curryAdd(1);
curryAdd(2);
curryAdd(); // 3
  • 简化参数传递:当函数需要多个参数时,可以使用柯里化函数将多个参数转换成一系列只接受单个参数的函数,从而简化参数传递

反柯里化

定义

反柯里化是将柯里化函数转换成接受多个参数的函数的过程。

反柯里化函数的返回值是一个函数,该函数接受一个对象作为参数,并调用该对象的原本方法并传递参数。

反柯里化的作用在于扩大函数的适用性,使本来只有特定对象所拥有的函数可以被任意对象所用。

例如将obj.func(arg1, arg2)转换为func(obj, arg1, arg2)的函数形式调用。

目前有一个对象obj和一个求和的函数,需要调用求和函数并让this指向obj

kotlin 复制代码
const obj = {a:1,b:2};

function sum(){
    return this.a + this.b;
}

可以通过.call.apply改变this指针指向

ini 复制代码
const res = sum.call(obj); // 3

也可以利用bind固化this指向并返回一个新函数

ini 复制代码
const newSum = sum.bind(obj);
console.log(newSum()); // 3

通用公式

javascript 复制代码
function uncurrying(fn){
    return function(){
        const context = Array.from(arguments).slice(1);
        return fn.apply(context,arguments);
    }
}

优缺点

反柯里化函数的优点:

  • 可读性:函数的调用变得更简单,只需要调用一个函数并传递一个对象作为参数即可

  • 可复用性:将一个预设 this 对象的函数转换成接受 this 对象的函数,从而可以在不同的对象上复用该函数

反柯里化函数的缺点:

  • 灵活性:函数的 this 对象变得固定,降低了函数的灵活性

适用场景

  • 复用函数:当多个对象需要调用同一个方法时,可以使用反柯里化函数将该方法转换成接受对象作为参数的函数,从而可以在不同的对象上复用该函数

  • 链式调用:当多个方法需要进行链式调用时,可以使用反柯里化函数将该方法转换成接受对象作为参数的函数,从而可以方便地进行链式调用

相关推荐
无巧不成书02181 小时前
Windows PowerShell执行策略详解:从npm报错到完美解决
前端·windows·npm·powershell执行策略·执行策略·npm.ps1·脚本报错
Z兽兽8 小时前
React@18+Vite项目配置env文件
前端·react.js·前端框架
SuniaWang8 小时前
《Spring AI + 大模型全栈实战》学习手册系列 · 专题六:《Vue3 前端开发实战:打造企业级 RAG 问答界面》
java·前端·人工智能·spring boot·后端·spring·架构
A_nanda9 小时前
根据AI提示排查vue前端项目
前端·javascript·vue.js
happymaker06269 小时前
web前端学习日记——DAY05(定位、浮动、视频音频播放)
前端·学习·音视频
~无忧花开~9 小时前
React状态管理完全指南
开发语言·前端·javascript·react.js·前端框架
LegendNoTitle10 小时前
计算机三级等级考试 网络技术 选择题考点详细梳理
服务器·前端·经验分享·笔记·php
@大迁世界10 小时前
1.什么是 ReactJS?
前端·javascript·react.js·前端框架·ecmascript
BJ-Giser11 小时前
Cesium 基于EZ-Tree的植被效果
前端·可视化·cesium
王码码203511 小时前
Flutter for OpenHarmony:Flutter 三方库 algoliasearch 毫秒级云端搜索体验(云原生搜索引擎)
android·前端·git·flutter·搜索引擎·云原生·harmonyos