进阶JavaScript柯里化函数原理咨询:代码逻辑与参数疑问
柯里化函数进阶示例拆解
先看你给出的核心代码:
const curry = (fn) => { return curried = (...args) => { if (fn.length !== args.length) { return curried.bind(null, ...args) } return fn(...args); }; } const totalNum = (x, y, z) => { return x + y + z } const curriedTotal = curry(totalNum); console.log(curriedTotal(10)(20)(30));
整体运行机制
这个curry函数的核心是通过闭包和函数绑定,逐步收集参数,直到参数数量匹配原函数的形参数量,再执行原函数。它利用fn.length(原函数的形参个数)作为判断是否触发原函数执行的依据。
(...args) 的值与来源
(...args)是剩余参数语法,用来收集每次调用柯里化函数时传入的所有实参,打包成一个数组。- 来源就是每次调用时传入的参数:
- 第一次调用
curriedTotal(10),args为[10] - 第二次调用返回的函数
(20),args为[10, 20] - 第三次调用
(30),args为[10, 20, 30]
- 第一次调用
curried.bind(null, ...args) 的作用
这行是实现参数累积的核心:
bind方法会生成一个新函数,把传入的...args作为新函数的预设参数——后续调用这个新函数时,这些预设参数会自动排在实参前面。null是绑定的this指向,这里原函数totalNum不需要特定this,所以传null即可。- 返回这个绑定后的新函数,相当于把已收集的参数"暂存"起来,等下次调用时和新传入的参数合并,继续累积。
示例分步执行流程
跟着curriedTotal(10)(20)(30)一步步拆解:
- 执行
curry(totalNum):fn指向totalNum,它的length为3(对应x、y、z三个形参)- 返回内部的
curried函数,赋值给curriedTotal
- 第一次调用
curriedTotal(10):args为[10],此时3 !== 1,不触发原函数- 执行
curried.bind(null, 10),返回一个预设了第一个参数为10的新函数
- 第二次调用返回的新函数
(20):- 预设参数
10和新传入的20合并,args变为[10, 20] 3 !== 2,继续执行curried.bind(null, 10, 20),返回预设了前两个参数的新函数
- 预设参数
- 第三次调用这个新函数
(30):- 预设参数和新传入的
30合并,args变为[10, 20, 30] - 此时
3 === 3,执行fn(...args)即totalNum(10,20,30),返回结果60,最终打印60
- 预设参数和新传入的
内容的提问来源于stack exchange,提问作者j obe
相关产品推荐
相关产品推荐

