題目
發現一道有意思的面試題:如何實現 add(1)(2)(3)=6 ?
首先簡單分析一下,我們就能發現這是一個函數傳值 return3次得到6 。
簡單實現
function add(a) {
return function (b) {
return function (c) {
return a + b + c;
}
}
}
利用閉包,執行add函數時return一個匿名函數,用於最終返回結果。
當然,這個方法有個明顯缺陷,就是如果函數變成 add(1)(2)(3)(4) ,我們就又要手動嵌套一層。
分析
有沒有什麼辦法呢? 有!
我們先把這個問題簡化一下:
如何實現函數對自身的調用呢,如: add()()() ?
function add () {
// 方法1:利用apply
return function () {
return add.apply();
}
// 方法2:
// return add;
}
那麼,問題就可以這麼實現:
function add () {
var args = Array.prototype.slice.call(arguments);
console.log(args);
var fn = function () {
var fn_args = Array.prototype.slice.call(arguments);
return add.apply(null, args.concat(fn_args));
};
return fn;
}
至此, add 函數的多層嵌套以及所有參數,我們都拿到了,下面只需要把參數相加就可以了。
但我們不能直接相加,因為我們 add 函數 return add.apply() 返回的是函數, 因此即使相加,值我們也是拿不到的。
valueOf
這裏我們要用到 valueOf 方法。
valueOf 方法返回指定對象的原始值。
function add () {
var args = Array.prototype.slice.call(arguments);
var fn = function () {
var fn_args = Array.prototype.slice.call(arguments);
return add.apply(null, args.concat(fn_args));
};
fn.valueOf = function () {
return args.reduce(function (a, b) {
return a + b;
});
};
return fn;
}
搞定!現在這個方法不僅支持 add(1)(2)(3) 而且支持 add(1,2,3) 。