记录科里化,检验自己的学习程度;
科里化定义:在计算机科学中,柯里化(Currying)是把接受多个参数的函数变换成接受一个单一参数(最初函数的第一个参数)的函数,并且返回接受余下的参数且返回结果的新函数的技术。这个技术由 Christopher Strachey 以逻辑学家 Haskell Curry 命名的,尽管它是 Moses Schnfinkel 和 Gottlob Frege 发明的。
--引用自百度百科
add(1)(2)(3)(4) = 10; 实现add函数
- 参数长度一定(类似上边的参数长度为 4);
let sum = (a,b,c,d)=>a+b+c+d;
function curry(sum){
let len = sum.length; // 参数的长度
let opts = [];
// 利用闭包 收集参数 当长度 == len 的时候
// 调用 sum
return function next(...arg){ // 收集参数
opts = opts.concat(arg);
if(opts.length < len){
return next;
} else {
return sum.apply(null,opts);
}
}
};
// 测试一下
let func = curry(sum);
console.log(func(1)(2)(3)(4)); // 10
console.log(func(1,2)(3)(4)); // 10
用到的知识点:闭包 迭代 我理解的 闭包:一种保存变量的机制 迭代的话 一定要注意边界
- 参数长度不定,以()为边界 类似 add(1)(2)(3)(4)();
来实现
function curry2(fn) {
let opts =[];
return function next(...args) {
opts = opts.concat(args)
// 和上边的只是边界条件不同
if(args.length){
return next
} else {
return fn.apply(null,opts);
}
}
};
let add2 = function () {
return [...arguments].reduce((prev,cur)=>prev+cur);
};
let func2 = curry2(add2);
console.log(func2(1)(2)(3)(4)()); // 10
console.log(func2(1)(2,3)(4)()); //10
- 不定边界 类似 add(1)(2)(3)(4)...(101)...
这个边界改怎么确定,是个最难的问题,先来看实现
function curry3(fn) {
let opts = [];
console.log('opts');
function next(...args) { // next仅仅用来收集参数
opts = opts .concat(args);
return next
}
// 字符类型
next.valueOf = function () {
return fn.apply(null, opts);
}
// 数值类型
next.toString = function () {
return fn.apply(null, opts);
}
return next;
};
let add3 = function () {
return [...arguments].reduce((prev,cur)=>prev+cur);
};
let func3 = curry3(add3);
func3(1)(2)(3)(4);
console.log(func3(1)(2)(3)(4)); // 10
console.log(func3(1)(2,3)(4)); //10
重写了next的 toString 和 valueOf 函数,当调用这两个函数的时候,执行add3这个方法, toString 和 valueOf 是隐式调用的,隐式调用发生在什么时候呢?
当函数执行 func3(1)(2)(3)(4); 完成这一行代码的时候,并没有执行隐式调用, 执行了 console.log(func3(1)(2)(3)(4)) 这一行代码,toString 才执行, 我并不是很清楚为什么会这样,我的理解是这样的,toString 和 valueOf 这两个函数的作用返回的是当前函数的值, func3(1)(2)(3)(4), 这一行代码虽然有返回值,但是并没有用到,所以并不执行toString和valueOf,而这一行 console.log(func3(1)(2)(3)(4)) 我们用到了,我们把值传进了 console.log()函数,用到了这个值,所以会执行 toString和valueOf,得出结论,值被用到就会执行 toString和valueOf
隐式调用比较常见的 if 判断条件里边的类型转换,操作符,函数传参,只要值被用到,就会发生隐式调用。
推荐阅读:柯里化与反柯里化
水平有限,简单的实现,难免有错误,欢迎指出。