Javascript中带有多个括号的闭包

Javascript中带有多个括号的闭包,javascript,closures,Javascript,Closures,有谁能解释一下,当没有更多的参数被传递时,这个函数是如何发出警报的。我不能清楚地理解它 function sum(a) { var sum = a function f(b) { sum += b return f } f.toString = function() { return sum } return f } alert( sum(1)(2) ) // 3 alert( sum(5)(-1)(2) ) // 6 alert( sum(6)

有谁能解释一下,当没有更多的参数被传递时,这个函数是如何发出警报的。我不能清楚地理解它

function sum(a) {

  var sum = a

  function f(b) {
    sum += b
    return f
  }

  f.toString = function() { return sum }

  return f
}

alert( sum(1)(2) )  // 3
alert( sum(5)(-1)(2) )  // 6
alert( sum(6)(-1)(-2)(-3) )  // 0
alert( sum(0)(1)(2)(3)(4)(5) )  // 15

警报
需要一个字符串。如果它没有得到字符串,它将尝试将它接收到的任何对象(函数是对象的一种类型)转换为字符串。如果对象具有
toString
方法,则将调用该方法来执行所述转换

要看的是这段代码

function f(b) {
    sum += b
    return f
  }

此函数返回对自身的引用,以便尽可能多次调用它。重要的是它有一个tostring函数可以被调用,因为tostring是在函数
sum()
中定义的,所以它可以访问变量
sum
及其当前值(该值由
f()
更改)函数的
sum
f
总是返回
f
函数,您可以无限次地调用它,而不会得到函数以外的结果

该值仅由
f
的重写
toString
方法返回(该方法实际返回一个数字):


alert
函数在将参数转换为字符串时隐式调用
toString
方法。

第一次调用函数时,第一个值存储在
sum
中。之后,将返回函数f(b),并将临时结果保存在
sum
中。在每次连续调用中,执行函数
f
——执行
sum+=b
,然后再次返回f。如果需要字符串上下文(例如在
警报
,或
控制台.log
),则调用
f.toString
,返回结果(
sum


在所有情况下,它都无法正常工作。。。问题是
.toString
应该返回一个字符串,因此提供的实现中的字符串方法将不起作用,例如。g<代码>总和(2)(3)。拆分()将导致错误

虽然我们可能会假设
sum()
结果总是预期为一个数字,但在某些情况下可能不是真的,并且可能很难调试,例如。G当我最初仅在jsbin.com上测试使用
.toString
编写的代码时,我注意到了这个问题(它在console.log参数上内部执行
split
,覆盖它)

相反,
.toString
应该看起来像
返回字符串(结果)。好消息是
.toString
(当没有
.valueOf
或现代
符号.toPrimitive
时)将处理原语转换,因此需要数字的代码也可以工作。这里可能存在的问题可能是由此导致的“双重”转换

更好的解决方案可能是使用一对
.toString
.valueOf
或者只使用一个
符号.toPrimitive
,如果您只针对现代浏览器

使用
符号的示例。toPrimitive

function sum(a) {
  let result = a;

  function f(b) {
    result += b;

    return f;
  }

  f[Symbol.toPrimitive] = hint => hint === 'string' ? String(result) : result;

  return f;
}
使用
.toString
.valueOf
对的示例

function sum(a) {
  var result = a;

  function f(b) {
    result += b;

    return f;
  }

  // avoiding double conversion which will happen in case of .toString
  f.valueOf = function() { return result; };
  f.toString = function() { return String(result); };

  return f;
}

所有对象都有一个
toString
函数,只是在大多数情况下它是默认的“[object Constructorname]”格式。在这种情况下,该方法被重写以产生结果。基本上,在第一个警报和(1)(2)中是a&b,在第二个警报中是和(6)(-1)(2)。现在函数如何理解(2)也是f(b)参数。@Babu摆脱a和b的思想。您可以考虑调用一次
sum()
,初始化
var sum
,然后在第一次调用后被覆盖,通过调用
f(b)
来处理每个连续调用(因为f本身每次都返回自身,从而可以进行进一步的链接),除非出现字符串上下文。现在清楚了吗?很好的解释。你能告诉我直接返回金额的代码吗。函数sum(a){var sum=a函数f(b){sum+=b return sum}//f.toString=function(){return sum}return f}sum(1)(2)@BabuArumugam:关键是你不能……你为什么需要这个?
alert( sum(6)(-1)(-2)(-3) )  // 0
           /\ function sum called, f returned
              /\ the returned function f is called, f returns itself
                  /\ again
                     /\ and again
                         /\ at last, alert() requires string context,
                            so f.toString is getting invoked now instead of f
function sum(a) {
  let result = a;

  function f(b) {
    result += b;

    return f;
  }

  f[Symbol.toPrimitive] = hint => hint === 'string' ? String(result) : result;

  return f;
}
function sum(a) {
  var result = a;

  function f(b) {
    result += b;

    return f;
  }

  // avoiding double conversion which will happen in case of .toString
  f.valueOf = function() { return result; };
  f.toString = function() { return String(result); };

  return f;
}