一道javascript面试题(闭包与函数柯里化)

时间:2021-10-27 13:13:37

要求写一个函数add(),分别实现能如下效果:

(1)console.log(add(1)(2)(3)(4)());//
(2)console.log(add(1,2)(3,4)());//
(3)console.log(add(1,2)(3,4));//

针对(1)和(2),有两种思路实现:纯闭包思路和函数柯里化思路。

一、闭包思路

(1)的解决方案(闭包实现)

function add(arg) {
// body...
let sum = 0;
sum+=arg;
return function (tmarg) {
// body...
if (arguments.length == 0) {
return sum;
}else{
sum+=tmarg;
return arguments.callee;
}
}
}

(2)的解决方案

function add(arg) {
// body...
let sum = 0;
sum = Array.prototype.slice.call(arguments).reduce((a,b) => {return a+b;},sum);
return function (tmarg) {
// body...
if (arguments.length == 0) {
return sum;
}else{
sum = Array.prototype.slice.call(arguments).reduce((a,b) => {return a+b;},sum);
return arguments.callee;
}
}
}

二、函数柯里化的思路

通俗的理解,由于函数柯里化具有这样的特性:它能够"积累"函数的参数(不管是foo(1,2,3)还是foo(1)(2)(3)这种链式形式)),并且延迟执行。可以将多个参数积累到一个数组中,在最后一步执行求和。
柯里化通用形式:

function curry(fn) {
// body...
var args = Array.prototype.slice.call(arguments,1);
return function () {
// body...
var innerArgs = Array.prototype.slice.call(arguments);
var finalArgs = args.concat(innerArgs);
console.log(finalArgs);
return fn.apply(null,finalArgs);
};
}

(2)的解决方案:

function add() {
let sum = 0;
var _args = Array.prototype.slice.call(arguments);
var tmpf = function(){
if(arguments.length === 0) {
sum = _args.reduce((a,b) => {return a + b;},sum);
}
_args.push.apply(_args,[].slice.call(arguments));
return tmpf;
}
}

针对问题(3):

function add(arg) {
// body...
let sum = 0;
sum = Array.prototype.slice.call(arguments).reduce((a,b) => {return a+b;},sum);
var tmpf = function (tmarg) {
// body...
if (arguments.length == 0) {
return sum;
}else{
sum = Array.prototype.slice.call(arguments).reduce((a,b) => {return a+b;},sum);
return tmpf;
}
};
tmpf.toString = tmpf.valueOf = function () {
// body...
return sum;
}
return tmpf;
}

完!

转载请注明原文出处:http://www.cnblogs.com/qcblog/p/6858947.html