先看一個問題
有一個函數 multiply
可以無限調用,如:multiply(1,2)(4)(1,2)(),求所有數的合。
分析:涉及到的點:
柯里化
,callee
CODE
var multiply = (function () {
let sum = 0;
return function() {
var arr = [].slice.call(arguments);
if(arr.length <=0) {
return sum;
}else {
arr.forEach(item => sum+=item)
}
return arguments.callee; //callee:正被執行的Function對象。
}
})();
var test = multiply(1,2)(4)(1,2)();
console.log(test);
思路解析
- 首先一個函數可以無限次調用,需要
return
一個function
。這個函數需要做的操作是計算和并且當無入參時返回結果。此時就需要通過返回函數本身來實現無限調用,返回函數本身可以通過return arguments.callee
或者return 函數名
這兩種方法。 - 入參不限并且統一處理就涉及到的是一個柯理化的概念。
柯里化: 是把接受多個參數的函數變換成接受一個單一參數(最初函數的第一個參數)的函數,并且返回接受余下的參數而且返回結果的新函數的技術。其實,柯里化就是用閉包原理實現函數參數的合并,然后再運行函數。
[].slice.call(arguments)
把偽數組轉化返回一個正常的Array. 然后通過閉包實現sum的累加。
鏈式函數
對于上面的問題如果沒有最后的(),該怎么寫呢。
var multiply = function () {
var sum = 0;
var _args = [].slice.call(arguments);
_args.forEach(item => {
sum += item;
});
function s() {
var args = [].slice.call(arguments);
args.forEach(item => {
sum += item;
});
return s
}
s.toString = function() {
return sum + '';
}
s.valueof = function () {
return sum;
}
return s;
};
var test = multiply(1, 2)(4)(1, 2);
console.log(test1);
解釋: multiply函數內部返回一個s函數,修改了期toString和valueof方法,目的是為了在進行類型轉化時返回值。