【问题标题】:Javascript function challenge add(1,2) and add(1)(2) both should return 3Javascript 函数挑战 add(1,2) 和 add(1)(2) 都应该返回 3
【发布时间】:2015-07-09 00:49:31
【问题描述】:

我的一个朋友要求我编写一个适用于这两种情况的函数

add(2,4)  // 6
add(2)(4) // 6

我的直觉是编写一个返回自身的 add() 函数,但我不确定我是否朝着正确的方向前进。这失败了。

function add(num1, num2){
    if (num1 && num2){
        return num1 + num2;
    } else {
        return this;
    }
}

alert(add(1)(2));

所以我开始阅读返回其他函数或返回自身的函数。

我会继续尝试,但如果有人有一个巧妙的解决方案,我很乐意看到它!

【问题讨论】:

  • @MarkC。像这样的问题需要一个客观的获胜标准才能成为 PPCG 的主题。在目前的状态下,这个问题不适合has been put on hold
  • 我认为@Partric Roberts 的答案更好,你能把他的答案标记为正确吗?

标签: javascript function closures challenge-response


【解决方案1】:

我写了一个curried function,它的valueOf()方法和function context (this)sum绑定,不管每次传递多少参数。

/* add function */
let add = function add(...args) {
  const sum = args.reduce((acc, val) => acc + val, this);
  const chain = add.bind(sum);
  chain.valueOf = () => sum;
  return chain;
}.bind(0);

/* tests */
console.log('add(1, 2) = ' + add(1, 2));
console.log('add(1)(2) = ' + add(1)(2));
/* even cooler stuff */
console.log('add(1, 2)(3) = ' + add(1, 2)(3));
console.log('add(1, 2, 3)(4, 5)(6) = ' + add(1, 2, 3)(4, 5)(6));
/* retains expected state */
let add7 = add(7);
console.log('let add7 = add(7)');
console.log('add7(3) = ' + add7(3));
console.log('add7(8) = ' + add7(8));

之所以需要这两种机制是因为add()的主体必须使用被调用函数的绑定上下文才能访问中间partial application的总和,并且调用站点必须使用valueOf()成员(隐式或显式)以获取最终总和。

【讨论】:

  • 在没有 console.log() 的情况下有什么方法可以完成这项工作吗?
  • @SarathSNair 是的,使用Number() 或一元+ 投射。
  • 怎么做?如果我只调用 add(1,2)(3) 而没有 console.log('add(1, 2)(3) = ' + add(1, 2)(3));
【解决方案2】:

Dr.Dobs Journal 上有一篇关于“Currying and Partial Functions in JavaScript”的文章准确描述了这个问题。

本文中找到的一个解决方案是:

// a curried add
// accepts partial list of arguments
function add(x, y) {
     if (typeof y === "undefined") { // partial
        return function (y) {
              return x + y;
        };
     }
   // full application
   return x + y;
}

【讨论】:

  • 而不是typeof y === "undefined"尝试arguments.length < 2,以防undefined被显式传递给y
【解决方案3】:
function add(num1, num2){
    if (num1 && num2) {
        return num1 + num2;
    } else if (num1) {
        return function(num2){return num1 + num2;};
    }
    return 0;
}

【讨论】:

  • add(0,x) 始终返回 0,无论 x 的值如何。 add(0)(x) 总是导致 TypeError
  • @Adam:对。在这种情况下,最好检查上面答案中提到的undefinedarguments.length
【解决方案4】:

您正在寻找的概念称为currying,它与函数转换和部分函数应用有关。当您发现自己一遍又一遍地使用几乎相同的参数调用相同的函数时,这很有用。

通过柯里化实现add(2)(6) 的示例如下所示...

function add(x,y) { 
  if (typeof y === 'undefined') {
    return function(y) {
      return x + y;
    }
  }
}

add(2)(4); // => 6

另外,你可以做这样的事情......

var add6 = add(6);
typeof add6; // => 'function'
add6(4);     // => 10

【讨论】:

    【解决方案5】:
    var add = function(){
      // the function was called with 2 arguments
      if(arguments.length > 1)
        arguments.callee.first_argument = arguments[0];
    
      // if the first argument was initialized
      if(arguments.callee.first_argument){
        var result = arguments.callee.first_argument + arguments[arguments.length - 1];
        arguments.callee.first_argument = 0;
    
        return result;
      }else{// if the function was called with one argument only then we need to memorize it and return the same function handler 
        arguments.callee.first_argument = arguments.callee.first_argument || arguments[0];
        return arguments.callee;
      }
    }
    console.log(add(2)(4));
    console.log(add(2, 4));
    

    依赖于环境的扩展解决方案:

    function add(){
      add.toString = function(){
        var answer = 0;
        for(i = 0; i < add.params.length; i++)
          answer += add.params[i];
        return answer;
      };
    
      add.params = add.params || [];
      for(var i = 0; i < arguments.length; i++)
        add.params.push(arguments[i])
    
      return add;
    }
    
    console.log(add(2)(4)(6)(8))
    console.log(add(2, 4, 6, 8));
    

    【讨论】:

      【解决方案6】:

      我们可以使用 Javascript 提供的闭包概念。

      代码sn-p:

      function add(a,b){
      
          if(b !== undefined){
      
              console.log(a + b);
              return;
      
          }
      
          return function(b){
              console.log(a + b);
          }
      
      }
      
      add(2,3);
      add(2)(3);
      

      【讨论】:

        【解决方案7】:

        一般而言,您需要就函数是否应该返回一个函数(用于使用更多参数调用)或最终结果达成一致。想象一下add 函数也必须像这样工作:

        add(1, 2, 3)(4, 5)  // -> 15
        

        ...然后它变得模棱两可,因为您可能想再次调用:

        add(1, 2, 3)(4, 5)(6)  // -> 21
        

        ...所以add(1, 2, 3)(4, 5) 应该返回一个函数,而不是 15。

        例如,您可以同意必须再次调用函数,但不带参数,以便获得数字结果:

        function add(...args) {
            if (args.length === 0) return 0;
            let sum = args.reduce((a, b) => a+b, 0);
            return (...args) => args.length ? add(sum, ...args) : sum; 
        }
        
        console.log(add()); // 0
        console.log(add(1,2,3)()); // 6
        console.log(add(1,2,3)(4,5)()); // 15
        console.log(add(1,2,3)(4,5)(6)()); // 21

        【讨论】:

          【解决方案8】:

          你可能认为他/她必须调用两次相同的函数,但如果你深入思考你会发现问题很简单,你必须调用一次 add 函数然后你需要调用什么永远 add 函数返回。

          function add(a){
              return function(b){
                  return a+b;
              }
          }
          console.log(add(20)(20));
          //output: 40
          

          您可以根据需要多次返回函数。假设 y = mx+c

          const y= function (m){
              return function(x){
                  return function (c){
                      return m*x+c
                  }
              }
          }
          
          console.log(y(10)(5)(10)); 
          //out put: 60
          

          【讨论】:

          • 没有深入思考,我注意到 OP 希望 add(2,4) 返回 6。
          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2022-11-30
          • 2023-03-20
          • 1970-01-01
          相关资源
          最近更新 更多