首页 > 代码库 > 一道javascript面试题(闭包与函数柯里化)

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

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

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

针对(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;
}

 

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