首先简要说一下什么是curry化 :它是一种通过把多个参数填充到函数体中,实现将函数转换成一个新的经过简化的(使之接受的参数更少)函数技术.(摘自:精通JavaScrtpt图灵计算机科学丛书-21页)
//写一个简单点的
function curry(fn/*function*/ , scope/*object?*/){
//取到除必须参数的其他参数,也就是第二个以后的所有参数,做一个缓存
var args = [].slice.call(arguments , 2);
console.log(args)
scope = scope || window;//这里是第二个参数也作为可选参数,加一个默认值
return function(){//返回一个新方法
return fn.apply(scope , args.concat([].slice.call(arguments)));
/**
* 每一个function都有一个apply方法和call方法
* 他们的作用基本是一样的,用来修改当前方法执行时的this指针
* 比如
* function test(a , b){
* this.alert(a + b);
* }
* test.call(window , 1 , 2);//运行test,将里面的this指向window,并且传参数为1 , 2
* test.apply(window , [1 , 2]);//运行test,将里面的this指向window,传参数为1 , 2
* 只不过是一个直接传参数,一个将参数作为数组传
* 上面的fn.apply(scope , args.concat([].slice.call(arguments)))
* 这里args本身就是一个数组,上面已经转换过了
* 在和当前的参数列表用数组的concat方法合并成一个新的数组,传给apply方法
* 并且将作用域绑定为scope
*/
}
}
//首先呢,
// [].slice.call(arguments)这个用法是把实参列表转换成一个真正的数组
//[].slice.call(arguments, 2)这样是取第几个往后的
//比如
// function test(){
// alert([].slice.call(arguments))
// }
//test(1,2,3,4,5)//这里就会弹出数组[1,2,3,4,5]
//function test2(){
// alert([].slice.call(arguments , 2));//取第二位往后的参数
//}
// test2('a' , 'b' , 1 , 2 , 3) 这里为弹出数组[1,2,3],前面的俩个会忽略
//ok,上面是一些小技巧,下来是科里化的问题
//执行curry(fn , scope , args...)
//第一个参数,明显是一个方法
//第二个参数是指定这个方法的this指向,也就是作用域
//然后接下来的参数会被缓存到那个变量args里面,当然也可以不传,是可选的
//执行curry之后,返回一个新的方法,执行这个方法,和直接执行的fn左右差距不大,但是可以用来锁定this作用域指向
//也可以用来缓存简化一些参数
//做个例子
var obj = {
testFn : function(a , b , c , d , e , f , g){//假设需要穿N多的参数
return a + b + c + d + e + f + g;
}
};
console.log(obj.testFn(1, 2 , 3 , 4 , 5 , 6 , 7));//返回这个参数所有的和28
//用科里化可以简写参数,将参数分次传递
var fn = curry(obj.testFn , obj , 1, 2 , 3 , 4);
//这里,第一个参数传方法,第二个参数传一个对象,后面传一部分参数
//这些参数会被缓存起来,而且整个方法暂时不会执行
console.log(fn(5 , 6 , 7));//28
//因为上面利用科里化已经缓存了部分参数,这里就可以简化参数,传剩下的几个参数就可以了
//上面将的是科里化的基本作用和里面的原理