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

确定函数是如何在闭包javascript中调用的,javascript,function,closures,lexical-closures,Javascript,Function,Closures,Lexical Closures,最近我在hackerrank遇到了一个问题,就是必须计算乘法运算并返回答案。比如说 function multiply(a,b) { return a*b; } 现在的问题是函数可能以不同的方式调用,例如 multiply(4,5); multiply(4)(5); multiply(4)(5)(6); 我知道我们必须对第二个问题,即乘法(4)(5)进行闭包。我已经为此编写了代码 function multiply(a,b) { return function(b) {

最近我在hackerrank遇到了一个问题,就是必须计算乘法运算并返回答案。比如说

function multiply(a,b) {
     return a*b;
}
现在的问题是函数可能以不同的方式调用,例如

multiply(4,5);
multiply(4)(5);
multiply(4)(5)(6);
我知道我们必须对第二个问题,即乘法(4)(5)进行闭包。我已经为此编写了代码

function multiply(a,b) {
  return function(b) {
    return a*b;
  }
}
现在,如果它的bed multiply函数被3个参数multiply(4)(5)(6)调用,该怎么办。如何识别函数是如何调用的,如何为所有输入编写通用解决方案


感谢您的帮助。谢谢

你很接近了,你要做的就是所谓的,一种利用闭包的技术

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

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,因此必须结束该链,但是javascript中的许多操作(所有数学操作,如-*/)都会推断出对valueOf的调用。

这种方法的问题是返回值的模糊性。它必须是一个
数字
和一个
函数
,两者同时存在

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

const wrap=(累加器,值)=>{
设fn=(…args)=>args.length?wrap(累加器,args.reduce(累加器,值)):fn;
fn.valueOf=()=>值;
返回fn;
}
设mul=wrap((a,b)=>a*b,1);
控制台日志(+mul(4,5));
控制台日志(+mul(4,5)(6));
控制台日志(mul(4,5)*6);
控制台日志(+mul(4)(5,6)(7)(8,9)(()(10));
//或者换个手术?
让add=wrap((a,b)=>a+b,0);
控制台日志(+add(1,2,3,4,5))

。作为控制台包装{top:0;最大高度:100%!important;}
阅读一些关于“currying”函数的教程查看本教程。下面将解释部分函数和咖喱在javascript中的工作原理。这将解决您的问题。但是这样
乘(3)(4)
将返回
f(c){…
不是12,不是吗?是的,这取决于OP来解决,我相信他可以,我觉得完全解决某人的黑客问题是不对的,但这应该是一个好的开始,当然,我明白你的意思。这似乎是一个非常有趣的问题。函数可以有自定义值().这样它就可以作为一个函数()同时也是一种价值。是的,咖喱是一个很棒的概念,它可以通过让你为特定目的重用一个多用途函数来提高代码库的效率。它的可读性非常好,而且它只是一个很酷和新颖的编程概念。我想看看这个vid系列,了解一些类似的概念javascript中的函数式编程有很多优点fun@artgb不可能。只是一些推断的方法,例如,您可以将valueOf更改为toString,然后
document.body.innerHTML=multiply(1)(2)(3)
(请参见jsbin)或
alert(multiply(1,2,3))
Jonas感谢allot的回答,它工作得很好,但我很难理解它是如何工作的。你能把它分解并解释一下吗?Thanks@kannan不客气;)我们可以换一种方式吗,我的意思是,你能具体问一下你不懂的部分吗?我不懂的第一件事是,在辩论中传递的“…”是什么(…args)@kannan如果没有,我们无法退出该链。该函数需要返回一个函数以使该链无限,因此也要公开结果的唯一方法是使其成为该函数的一部分