zoukankan      html  css  js  c++  java
  • 一道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;
    }

    完!

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

  • 相关阅读:
    Maybe You Don't Know ! 如何比较两个引用是否指向同一个对象?
    记录一点项目心得...
    SharePoint 站点模版
    ObjectSpaces,See you in 2006...
    CLR如何实现线程同步
    Using 1.1, Waiting 2.0 & EasyThread
    在SharePoint中的Workflow引擎开发完成
    ViewState
    《WalkThrough WebPart 入门指南二》完成
    隐藏在.NET中的IoC?
  • 原文地址:https://www.cnblogs.com/qcblog/p/6858947.html
Copyright © 2011-2022 走看看