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

时间:2017-11-14 13:19:26

标签: javascript function closures lexical-closures

最近我在hackerrank面临一个问题,即必须计算乘法运算并且必须返回答案。例如

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

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

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

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

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

现在如果已经使用3个参数乘以(4)(5)(6)调用了它的乘法函数。如何识别函数的调用方式以及如何为所有输入编写通用解决方案。

感谢任何帮助。谢谢

3 个答案:

答案 0 :(得分:3)

要拥有无限的callchain,你需要一些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;
}

这种变量currying的问题在于它的无限,所以theres(通常)无法结束它。

multiply(1) // func :/

然而在javascript中它可以为函数分配方法,所以我们可以很容易地调用方法而不是函数来结束链:

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

所以你可以这样做:

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

+等于 valueOf ,因此需要结束链,但是对 valueOf 的调用是由javascript中的许多操作推断的(所有数学运算如 - * /).

答案 1 :(得分:1)

这种方法的问题在于返回值的模糊性。它必须同时是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;}




这种方法的缺点是,它变得如此灵活(和暧昧),它几乎没用,因为它太难以理解你在使用时会得到什么结果这是内联的。如果你将某些功能用于做一个类型测试怎么办?那你就麻烦了。

答案 2 :(得分:0)

你关闭了,你要做的事情被称为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)