短视频开源源码,js函数柯里化
短视频开源源码,js函数柯里化
维基百科: 柯里化(英语:Currying),又译为卡瑞化或加里化,是把接受多个参数的函数变换成接受一个单一参数(最初函数的第一个参数)的函数,并且返回接受余下的参数而且返回结果的新函数的技术。(这里说的是 返回一个接受单一参数的函数,我觉得我们实现的时候,可以更灵活,返回一个可以接受任意多参数的函数)
curry 的概念很简单:只传递给函数一部分参数来调用它,让它返回一个函数去处理剩下的参数。
// 原函数
var add = function(x,y) {
return x + y;
};
// 简单curry化后 应该是:
var add = function(x) {
return function(y) {
return x + y;
};
};
// 实现分开传参的目的
// 先加10
var addTen = add(10);
// 再加5
addTen(5); // 15
addTen(10); // 20
好处: 可以固定相同参数,实现函数调用传参的简单化。
举个例子,计算一个长方体的体积,如果长方体长和宽是不变,高度是发生变化的。
一般情况下我们会这么做:
function volumn(l,w,h) {
return l*w*h
}
// 计算过程会变成这样
let V1 = volumn(10,20,30)
let V2 = volumn(10,20,20)
let V3 = volumn(10,20,15)
如果我们把volumn函数柯里化,变成如下函数:
function curry_volumn(l,w) {
return function(h) {
return l*w*h
}
}
// 计算过程可以优化如下
// 先传入长和宽,得到一个新函数
let square = curry_volumn(x,y)
// 再计算体积
let V1 = square(30)
let V2 = square(20)
let V3 = square(15)
例子简单,大家自己体会其中的好处。下面我们就是要实现一个curry工具。
需要注意传入工具函数的函数参数是不一定的。
// 思路:
// 1. curry工具函数 接受一个函数返回一个函数,框架如下:
// function curry(fn) {
// return function(...args) {}
// }
// 2. 返回的函数可以接受一个参数或者多个参数,
// a.如果args长度大于等于 fn.length(形参),直接返回fn函数的执行结果
// b.如果args长度小于 fn.length(形参),继续返回一个函数,返回的函数需要继续执行第二步的递归调用,别且记录前几次输入的参数,知道参数长度大于等于fn.length,返回fn执行结果
// function curry(fn) {
// return function(...args) {
// if(args.length >= fn.length) {
// 如果传入参数长度等于原函数形参长度,直接返回结果
// } else {
// 返回一个函数,函数内部需要重新比较args.length >= fn.length,于是我封装了递归函数 rec
// }
// }
// }
// 柯里化工具函数
function curry(fn) {
// 获取形参的长度
return function(...args) {
if(args.length >= fn.length) {
// 如果传入参数长度等于原函数形参长度,直接返回结果
return fn.apply(this, args)
} else {
// 否则返回一个函数
let length = args.length;
return rec;
function rec(...others) {
if(others.length + length >= fn.length) {
return fn.apply(this, args.concat(others))
} else {
args = args.concat(others)
length = others.length + length
return rec
}
}
}
}
}
// 用上面的例子做测试
function volumn(l, w, h) {
return l * w * h
}
let curry_volumn = curry(volumn)
let square = curry_volumn(10, 20)
console.log(square(10)) // 2000
console.log(square(20)) // 4000
console.log(square(30)) // 6000
// 测试传入不同数量的参数
console.log(curry_volumn(10)(20)(30)) // 6000
console.log(curry_volumn(10)(20,30)) // 6000
console.log(curry_volumn(10,20)(30)) // 6000
console.log(curry_volumn(10)(20)(3
短视频开源源码,js函数柯里化
浙公网安备 33010602011771号