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

  • 相关阅读:
    vs2005中 fstream 不支持中文路径问题的解决方法:
    CString char* string 互转
    OpenGl显示,任意大小的图片作为背景
    combo box
    Android 开发环境搭建
    打开子对话框 选择文件
    (转)Static MemoryLayout_shadow memory
    (转)深入剖析I/O约束
    (转)set_input_delay/ set_output_delay之图解
    (转)PrimeTime分析流程
  • 原文地址:https://www.cnblogs.com/qcblog/p/6858947.html
Copyright © 2011-2022 走看看