JS函数柯里化:从函数arguments->柯里化的理解!!!

前言

本文通过函数中arguments对象,结合闭包递归思想剩余参数来逐步详细地掌握对柯里化的理解。

Arguments对象

这是一个简单的三参数加法函数。

add函数中存在一个"参数总管 ",能够访问函数中的参数,即arguments对象。

js 复制代码
function add(a, b, c) {
    return a + b + c
}
add(1, 2, 3)

何为arguments对象?

MDN WEB 文档是这样描述的: arguments 是一个对应于传递给函数的参数的类数组对象

什么是类数组对象?

我们都知道在JavaScript中,函数本质上是一种特殊的对象 ,能够作为值传递并且"类数组 " 意味着arguments长度属性且索引从零开始的,虽然有length属性,for也可以进行迭代,但它没有Array的内置方法。

js 复制代码
console.log(console.log(arguments.map(item => item + 1)))
//typeError: arguments.map is not a function

则我们可以利用arguments进行访问函数参数。

js 复制代码
add.length // 3
console.log(arguments[0]) // 1

我们也可以将类数组转为数组

js 复制代码
const args = Array.from(arguments) 
console.log(arguments) // [object Arguments]
console.log(args) // [object Array]

对于函数的这个特性,我们能够实现对函数柯里化

柯里化(Curring)

什么是柯里化柯里化指的是将一个多参数的函数拆分成一系列函数,每个拆分后的函数都只接受一个参数(unary)

实现原理:我们可以通过使用arguments对象、递归算法、闭包和剩余参数(Rest Parameters)来实现函数柯里化

我们知道,递归能将一个问题分成多个类似子问题 ,于是我们能用递归将参数分割成一个一个的,并使用剩余参数将其一个一个收集起来,直到收集完毕执行原函数(add)。

柯里化子过程即:

js 复制代码
function add(...args) {
    console.log(args); // [1,2,3]
    return (...newArgs) => {
        const arr = [...args, ...newArgs]
        // arr = [...args = [1,2,3] , ...newArgs = [7,8,9]]
        console.log(arr);// [1,2,3,7,8,9]
    }
}
add(1, 2, 3)(7, 8, 9)

fn参数是最终要执行的功能,fn在函数judge 中被引用,但不是在其内部定义的,所以是闭包中的自由变量 。当judge 函数被定义时,它能够访问到定义它的作用域中的变量(即curry 函数作用域),所以judge 函数能够访问到fn函数。

柯里化完整代码如下:

js 复制代码
function add(a, b, c) {
    return a + b + c
}

add(1, 2, 3)
function curry(fn) {
    let judge = (...args) => {
        if (args.length === fn.length) {
            // 递归出口(满足参数个数)
            return fn(...args)
        }
        return (...newArgs) => judge(...args, ...newArgs);
    }
    return judge;
}

let addCurry = curry(add)

console.log(addCurry(1)(2)(3)); // 6

执行过程即:

text 复制代码
第一次调用:addCurry(1)
args = [1]
参数不够,返回新函数

第二次调用:addCurry(1)(2)
args = [1, 2]
参数不够,返回新函数

第三次调用:addCurry(1)(2)(3)
args = [1, 2, 3]
参数够了,执行原函数

所以柯里化有什么用?

  • 参数复用
  • 延迟执行
  • 提高代码可读性

总结

柯里化 可以形象理解为集齐7颗龙珠(参数 )即可召唤神龙(原函数)!

相关推荐
Hilaku16 分钟前
如何用隐形字符给公司内部文档加盲水印?(抓内鬼神器🤣)
前端·javascript·面试
guxuehua19 分钟前
Monorepo Beta 版本发布问题排查与解决方案
前端
猫头虎-前端技术20 分钟前
小白也能做AI产品?我用 MateChat 给学生做了一个会“拍照解题 + 分步教学”的AI智能老师
前端·javascript·vue.js·前端框架·ecmascript·devui·matechat
b***666121 分钟前
前端的dist包放到后端springboot项目下一起打包
前端·spring boot·后端
栀秋66622 分钟前
ES6+新增语法特性:重塑JavaScript的开发范式
前端·javascript
爱分享的鱼鱼23 分钟前
Vue动态路由详解:从基础到实践
前端
未来之窗软件服务26 分钟前
幽冥大陆(三十七)文件系统路径格式化——东方仙盟筑基期
前端·javascript·文件系统·仙盟创梦ide·东方仙盟
维维酱29 分钟前
Vite 构建中的两个典型问题:代码分割命名与循环依赖
前端
VaJoy30 分钟前
Cocos Creator Shader 入门 (21) —— 高斯模糊的高性能实现
前端·cocos creator
前端加油站31 分钟前
使劲折腾Element Plus的Table组件
前端·javascript·vue.js