确定函数在闭包中是如何被调用的 javascript

Identify how the function has been called in closure javascript

最近我在 hackerrank 遇到一个问题,它必须计算乘法运算并且必须 return 答案。例如

function multiply(a,b) {
     return a*b;
}

现在问题是函数可能会以不同的方式调用,例如

multiply(4,5);
multiply(4)(5);
multiply(4)(5)(6);

我知道我们必须关闭第二个方法,即 multiply(4)(5)。我已经为此编写了代码

function multiply(a,b) {
  return function(b) {
    return a*b;
  }
}

现在如果用 3 个参数 multiply(4)(5)(6) 调用它的 multiply 函数会怎样。我如何确定该函数是如何被调用的以及我如何为所有输入编写一个通用解决方案。

感谢任何帮助。谢谢

你很接近,你正在尝试做的事情叫做 currying,一种利用闭包的技术。

在这种情况下,您的函数一次只能接受一个参数:

function multiply(a) {
    return function(b) {
        return a * b;
    }
}

现在你可以说

function multiplyBy5 = multiply(5);
console.log(multiplyBy5(4)); //would log 20

如果您只希望最多有 3 个参数,您可以这样做:

function multiply(a) {
    return function(b) {
        return function(c) {
            c = c || 1;
            return a * b * c;
        }
    }
}

这使得 c 成为可选参数。您可以通过

调用该函数
multiply(4)(5)()

//or

multiply(4)(5)(6)

要拥有无限的调用链,您需要一些 js 技巧:

function multiply(...args){
  //make the chain endless through using some recursive like stuff:
  const func = (...args2) => multiply(...args,...args2);
  //the chains endpoint:
  func.valueOf = function(){
     return args.reduce((a,b) => a*b);
  };
  return func;
}

这种变量柯里化的问题是它是无限的,所以(通常)没有办法结束它。

multiply(1) // func :/

但是在 javascript 中,可以将方法分配给函数,这样我们就可以轻松地在某些时候调用方法而不是函数来结束链:

multiply(1)(2)(3).valueOf()

所以你可以简单地做:

 console.log(
  +multiply(1,2,3)(4)(5),
  +multiply(1,2)
);

+ 等于 valueOf 并且因此是结束链所必需的,然而这个对 valueOf 的调用被许多操作推断出来在 javascript(所有数学运算,如 - * /)。

这种方法的问题是返回值不明确。它必须同时是 Numberfunction

由于 valueOf() 方法,您可以模拟该行为,但我很少建议在生产中使用它。

const wrap = (accumulator, value) => {
  let fn = (...args) => args.length? wrap(accumulator, args.reduce(accumulator, value)): fn;
  fn.valueOf = () => value;
  return fn;
}

let mul = wrap((a,b) => a*b, 1);

console.log(+mul(4,5));
console.log(+mul(4,5)(6));
console.log(mul(4,5) * 6);
console.log(+mul(4)(5,6)(7)(8,9)()(10));

//or maybe a different operation?
let add = wrap((a,b) => a+b, 0);

console.log(+add(1,2,3,4,5));
.as-console-wrapper{top:0;max-height:100%!important;}

这种方法的缺点是,它变得非常灵活(而且模棱两可),几乎没有用,因为很难掌握在某处内联使用它时会得到什么结果。如果您将其输入某些函数进行类型检查怎么办?那你就麻烦了。