1.函數(shù)的柯里化定義
創(chuàng)建已經(jīng)設(shè)置好一個或多個參數(shù)的函數(shù)筑悴,基本方法是使用一個閉包返回一個函數(shù)。
2.經(jīng)典面試題
實現(xiàn)一個add函數(shù),完成以下功能:
console.log(add(1,2,3)); //6
console.log(add(1)(2)(3)); //6
要想創(chuàng)建出一個通式宝鼓,很容易想到用遞歸來解決,但是遞歸需要一個結(jié)束條件巴刻,這里的結(jié)束條件怎么確定呢席函?
首先可以看一下console.log()函數(shù)的用法:
- 如果傳入?yún)?shù)是一個函數(shù),那么就會默認調(diào)用默認toString()方法冈涧,將函數(shù)的定義打印出來
- 如果定義了toString()或valueOf()方法茂附,就會調(diào)用valueOf() > toString()方法正蛙,valueOf()優(yōu)先級高于toString()方法
因此這里我們可以通過自定義toString()方法來模擬結(jié)束條件,方法如下:
function add(){
var args=Array.prototype.slice.call(arguments);
function adder(){
var newArgs=Array.prototype.slice.call(arguments);
args=args.concat(newArgs);
return adder; //每次調(diào)用后返回自身函數(shù)對象营曼,可以進行連續(xù)調(diào)用
}
adder.toString=function(){
return args.reduce(function(previos,current){
return previos+current;
});
}
return adder;
}
主要的思路就是乒验,利用閉包來保存每一次傳入函數(shù)的參數(shù)到args變量中,并且返回adder函數(shù)自身蒂阱,最后打印的時候調(diào)用函數(shù)對象的toString方法將所有的參數(shù)相加锻全。
3.柯里化通式
柯里化通式可以傳入一個函數(shù)和要綁定的參數(shù),返回包裝后的函數(shù):
function curry(func){
var args=Array.prototype.slice.call(arguments,1);
return function(){
var newArgs=Array.prototype.slice.call(arguments);
args=args.concat(newArgs);
return func.apply(null,args); //調(diào)用func時要用apply調(diào)用录煤,參數(shù)都包含在數(shù)組中
}
}
var sum=curry(function(){
var args=Array.prototype.slice.call(arguments);
return args.reduce(function(a,b){
return a+b;
});
},1);
console.log(sum(2,3));
4.實現(xiàn)函數(shù)柯里化的bind函數(shù)
實現(xiàn)函數(shù)柯里化的bind函數(shù)可以分兩次傳入?yún)?shù)鳄厌,每次傳入的參數(shù)都會通過閉包,保存在外部函數(shù)作用域內(nèi)妈踊。
function bind(func,context){
var args=Array.prototype.slice.call(arguments,2);
return function(){
var newArgs=Array.prototype.slice.call(arguments);
args=args.concat(newArgs);
return func.apply(context,args);
}
}
var a={
name: 'jc',
print: function(){
var str=Array.prototype.join.call(arguments,' ');
console.log(this.name+' '+str);
}
};
var b=bind(a.print,a,'first');
b('second'); //jc first second
5.函數(shù)內(nèi)部對象arguments
在函數(shù)體內(nèi)可以通過arguments對象訪問參數(shù)數(shù)組了嚎,但是arguments對象只是與數(shù)組相似,并不是Array的實例廊营,可以通過索引訪問參數(shù)歪泳,有l(wèi)ength長度屬性,不過可以通過call和apply間接調(diào)用數(shù)組的方法:
Array.prototype.slice.call(arguments)
[].slice.call(arguments)
數(shù)組這些方法應(yīng)該也是通過索引來訪問元素實現(xiàn)的露筒。