一. 柯里化函数实现:
1. 使用函数的length+arguments+apply的相关知识
var slice = Array.prototype.slice
var curry = function (fn) {
var args = slice.call(arguments, 1)
return _curry.apply(this, [fn, fn.length].concat(args))
function _curry(fn, len) {
var oArgs = slice.call(arguments, 2);
var args = oArgs.concat(slice.call(arguments))
if (args.length >= len) {
return fn.apply(this, args)
return _curry.apply(this, [fn, len].concat(args))
2. 使用函数的length + 扩展运算符... + apply的知识:
var curry = function (fn, ...arg1) {
return _curry.apply(this, [fn, len, ...arg1])
function _curry(fn, len, ...rest1) {
return function (...rest2) {
var args = [...rest1, ...rest2]
if (args.length >= len) {
return fn.apply(this, args)
return _curry.apply(this, [fn, len].concat(args))
实例运用:
测试计算总和的功能:
function calcSum(num1, num2, num3) {
return num1 + num2 + num3
var calcSum2 = function (...args) {
// const arr = Array.from(arguments);
const arr = Array.prototype.slice.call(arguments, 0);
// const arr = Array.of(...args);
return arr.reduce((obj, cur) => {
var calcSumCurry = _curry(calcSum2, 4)
log(calcSumCurry(3, 4, 5, 6))// 18
log(calcSumCurry(3)(4)(5)(6))//18
log(calcSumCurry(3)(4, 5)(6))//18
var calcSumCurry = curry(calcSum, 3)
log(calcSumCurry(4, 5))//12
log(calcSumCurry(4)(5))//12
每次只要在最后执行空参函数, 就开始计算, 下一次重新开始
function _curry(fn, len) {
var oArgs = slice.call(arguments, 2);
var args = oArgs.concat(slice.call(arguments));
if (arguments.length === 0) {
if (args.length >= len) {
return fn.apply(this, args);
return console.warn('curry: 参数长度不足')
return _curry.apply(this, [fn, len].concat(args))
var calcSum2 = function (...args) {
// const arr = Array.from(arguments);
const arr = Array.prototype.slice.call(arguments, 0);
// const arr = Array.of(...args);
return arr.reduce((obj, cur) => {
var calcSumCurry = _curry(calcSum2, 4)
log(calcSumCurry(3, 4, 5, 6)())// 18
log(calcSumCurry(3)(4)(5)(6)())//18
log(calcSumCurry(3)(4, 5)(6)())//18
log(calcSumCurry(3)(4, 5)()) // curry: 参数长度不足
想要一直累加:
var slice = Array.prototype.slice
function curry(fn, len0) {
const len = len0 || fn.length
if (arguments.length === 0) {
if (curArgs.length >= len) return fn.apply(this, curArgs)
return console.warn('curry: 参数长度不足')
Array.prototype.push.apply(curArgs, [].slice.call(arguments));
var calcSum2 = function (...args) {
// const arr = Array.from(arguments);
const arr = Array.prototype.slice.call(arguments, 0);
// const arr = Array.of(...args);
return arr.reduce((obj, cur) => {
var calcSumCurry = curry(calcSum2, 4)
log(calcSumCurry(3, 4, 5)())// curry: 参数长度不足
log(calcSumCurry(4)(5)())// 21
严格模式下callee会报错, 可以改成:
var slice = Array.prototype.slice
function curry(fn, len0) {
const len = len0 || fn.length
return function start () {
if (arguments.length === 0) {
if (curArgs.length >= len) {
if(tag === 'end') return console.warn('curry: 参数长度不足, 请核对参数后重试')
return fn.apply(this, curArgs)
return console.warn('curry: 参数长度不足')
Array.prototype.push.apply(curArgs, [].slice.call(arguments));
var calcSum2 = function (...args) {
const arr = Array.prototype.slice.call(arguments, 0);
return arr.reduce((obj, cur) => {
var calcSumCurry = curry(calcSum2, 4)
log(calcSumCurry(3, 4, 5)())
log(calcSumCurry(4)(5)())
柯里化log方法:
var slice = Array.prototype.slice;
var curry = function (fn, length) {
var args = slice.call(arguments, 2)
return _curry.apply(this, [fn, length || fn.length].concat(args))
function _curry(fn, len) {
var oArgs = slice.call(arguments, 2);
var args = oArgs.concat(slice.call(arguments));
if (args.length >= len) {
return fn.apply(this, args);
return _curry.apply(this, [fn, len].concat(args))
function log(logLevel, msg) {
console.log(`${logLevel}:${msg}:::${Date.now()}`)
const curryLog = curry(log);
const debugLog = curryLog("debug");
const errLog = curryLog("error");
debugLog("testDebug1");//debug:testDebug1:::1696145622354
debugLog("testDebug2");//debug:testDebug2:::1696145622360
errLog("testError1");//error:testError1:::1696145622360
errLog("testError2");//error:testError2:::1696145622360
二. 非柯里化的实现方式:
1. 偏函数
偏函数求和:
const args = [].slice.call(arguments, 1)
const newArgs = args.concat([].slice.call(arguments));
return fn.apply(this, newArgs)
function calcSum(...args) {
return arr.reduce((obj, cur) => {
const pCalcSum = partial(calcSum, 10);
console.log(pCalcSum(11, 12))
2. 反柯里化
1. 反柯里化方法的几种写法:
Function.prototype.unCurry=function() {
return Function.prototype.call.apply(self, arguments)
Function.prototype.unCurry=function() {
return this.call.bind(this)
Function.prototype.unCurry=function() {
return (...args) => this.call(...args)
2. 反柯里化实例运用:
1) 克隆数组
return function(context) {
return fn.apply(context, Array.prototype.slice.call(arguments, 1));
Function.prototype.unCurry = function () {
return Function.prototype.call.apply(self, arguments)
var clone = Array.prototype.slice.unCurry()
console.log('a == b', a === b);
var clone = unCurry1(slice)
console.log('a == b', a === b);
2) 生成类数组
return function(context) {
return fn.apply(context, Array.prototype.slice.call(arguments, 1));
Function.prototype.unCurry = function () {
return Function.prototype.call.apply(self, arguments)
var push = Array.prototype.push.unCurry();
unCurry1([].push)(obj, 7, 8, 9, 10)