[面试题目]如何实现multi(2)(3)(4)=24?

被一道面试题目难到了。
有函数multi(2)(3)(4)=24,算法是2X3X4=24。
求解multi函数。

求大神解答~

------------------分割线---------------------
最终采纳了@Ende93 的答案,感觉更优美一些。但是代码需要调整一下:

function multi(n){
  var fn = function(x) {
    return multi(n * x);
  };
  
  fn.toString = function() {
    return n;
  };
  
  return fn;
}

demo: http://jsfiddle.net/etianqq/7sjo4nwt/

------------------分割线---------------------
谢谢 @kikong 的comments,我之前想法是仓促些,之所以demo里面显示为24,是因为dom操作时自动调用了function.toString(),所以显示为数字了。
如果直接console.log(multi(2)(3)(4))--->function... ,如果是console.log(multi(2)(3)(4)+1)--->25.
所以,上面的方案还是有所欠缺的。

阅读 5.9k
评论
    14 个回答
    • 519

    首先返回值要是函数,其次要传递值:

    function multi(n){
      var fn = function(x) {
        return multi(n * x);
      };
      
      fn.valueOf = function() {
        return n;
      };
      
      return fn;
    }
    
    multi(1)(2)(3)(4) == 24; // true

    上诉代码来自于:codewar 加法链 Best Practices

      这不就是函数柯里化嘛。
      最简单的方式是定义一个正常的函数,然后用lodash或underscore或者其他类似库完成柯里化。方法如下:

      var baseFun = function(a, b, c){
        return a * b * c;
      }
      var multi = _.curry(baseFun);
      console.log(multi(2)(3)(4));

      需要注意的是,柯里化需要指定总参数个数,在lodash中如果未指定则视为this.length,在上例中也就是3.
      柯里化后的函数将在连续调用n次后返回所需的结果,n为刚刚说的参数个数。

      当然,你也可以不用柯里化的方式,直接按对方的逻辑要求用递归简单的实现一下。。

      function multi(v, last, times){
        times = (times || 0) + 1;
        last = (last || 1) * v;
        if(times < 3) {
          return function(v) {
            return multi(v, last, times);
          }
        } else {
          return last;
        }
      }
      console.log(multi(2)(3)(4));
        function curry(fn){
           var value;
           var callback = function(next){
              value = typeof value === "undefined" ? next : fn.apply(null,[value,next]);
              return callback;
           }
           callback.valueOf = callback.toString = function(){
             return value;
           
           }
           return callback
        }
        //加
        function add(x,y){
          return x + y
        }
        //减
        function minus(x,y){
          return x -y
        }
        //乘
        function multiply(x,y){
          return x * y;
        }
        //除
        function divide(x,y){
          return x / y;
        }
        curry(add)(2)(3)(4)(5)(6) //2+3+4+5+6=20
        curry(minus)(2)(3)(4)(5)(6) //2-3-4-5-6=-16
        curry(multiply)(2)(3)(4)(5)(6) //2*3*4*5*6=720
        curry(divide)(2)(3)(4)(5)(6) //2 / 3 / 4/ 5 /6 = 0.00555555...
          • 26.5k

          你指的是这样么?

          var multi = function(num1){
                  return function(num2){
                          return function(num3){
                                  return num1 * num2 * num3;
                          };
                  };
          };

            var baseFun = function(a, b, c){
            return a b c;
            }
            var multi = _.curry(baseFun);
            console.log(multi(2)(3)(4));

              var multi = x => y => z => x * y * z;
              
                • 5.6k
                function multi(num){
                  return function(secondNum){return function(thirdNum){return num*secondNum*thirdNum}}
                }

                  函数curry化,提供一个类似的思路:

                  函数Curry(柯里)化(部分传参,返回一个已传部分参数的函数;适用于公用一个函数,且传给改函数的部分参数是相同的情况)

                  function curry (fn) {
                       var slice = Array.prototype.slice,
                            old_args = slice.call(arguments, 1);
                       return function () {
                            var new_args = slice.call(arguments),
                                 args = old_args.concat(new_args);
                            return fn.apply(null, args);
                       }
                  }

                  var add = function (x, y, z) {
                       return x+y+z;
                  }

                  //一步curry化
                  curry(add, 1)(2, 3);     //返回6

                  //两步curry化
                  var addOne =  curry(add, 1);
                  var addTwo = curry(addOne, 2);
                  addTwo(3);     //返回6

                    • 18.4k

                    实现1:)

                    var multi=function(arg0){
                        return function(arg1){
                            return function(arg2){
                                return arg0*arg1*arg2
                            }
                        }
                    };

                    实现2:要多调用一次,可能和题目的要求不符,但提供了一种可以更多参数调用的可能,参考下

                    var multi=(function(){
                    
                        var result=1;
                        return function __multi__(arg){
                            if(!arg){
                                return result;
                            }
                            result=result*arg;
                            return __multi__;
                        };
                    }());
                    ···
                    console.log(multi(2)(3)(5)());
                        • 1
                        • 新人请关照

                        currying。撸主可以去查一下~

                          这道题对于懂得/或者习惯函数式编程的不是事,但是对于一般的命令式/OO程序员一开始还真不容易让绕清楚。

                            看了各位大神的解答后,感觉很受启发。我试着写了一个科里化函数:

                            var curry = function(func) {
                                var that=this;
                                var curry_func = function() {
                                    var this_func = arguments.callee;
                                    var new_params = this_func.params.slice();
                                    for(var i=0;i<arguments.length;i++)
                                        new_params.push(arguments[i]);
                                    if(new_params.length >= func.length)
                                        return func.apply(that, new_params);
                                    else{
                                        // dirty way to copy function
                                        eval('var new_func =' + this_func.toString());
                                        new_func.params = new_params;
                                        return new_func;
                                    }
                                };
                                curry_func.params = [];
                                return curry_func;
                            };
                            
                            // 原函数
                            var test_func = function(a, b, c) { return a*b*c; };
                            
                            var f0 = curry(test_func);
                            
                            // 实现科里化功能
                            console.log(f0(2,3,4));
                            console.log(f0(2)(3)(4));
                            console.log(f0(2,3)(4));
                            
                            // 科里化结果不会互相影响
                            f1 = f0(2,3);
                            console.log(f1(10));
                            console.log(f1(11));

                              fn.toString那一步是什么意思求解

                              该答案已被忽略,原因:

                                撰写回答

                                登录后参与交流、获取后续更新提醒