首先簡要說一下什麼是curry化 :它是一種經過把多個參數填充到函數體中,實現將函數轉換成一個新的通過簡化的(使之接受的參數更少)函數技術.(摘自:精通JavaScrtpt圖靈計算機科學叢書-21頁)數組
//寫一個簡單點的緩存
function curry(fn/*function*/ , scope/*object?*/){app
//取到除必須參數的其餘參數,也就是第二個之後的全部參數,作一個緩存函數
var args = [].slice.call(arguments , 2);this
console.log(args)spa
scope = scope || window;//這裏是第二個參數也做爲可選參數,加一個默認值指針
return function(){//返回一個新方法對象
return fn.apply(scope , args.concat([].slice.call(arguments)));作用域
/**io
* 每個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
//由於上面利用科裏化已經緩存了部分參數,這裏就能夠簡化參數,傳剩下的幾個參數就能夠了
//上面將的是科裏化的基本做用和裏面的原理