我是JavaScript世界的新手。今天在使用JavaScript时我发现了以下片段:
function sum (a) {
var sum = a;
function f (b) {
sum += b;
return f;
}
f.toString = function () {
return sum;
}
return f
}
//Calling the function
console.log(sum(4)(5));
你能帮我理解f.toString
何时被执行?
答案 0 :(得分:4)
将对象传递给console.log()
时,会调用.toString()
以打印出该值。
因此,
sum(4)
返回一个函数。随后调用该函数
sum(4)(5)
也会返回一个函数。然后传递给console.log()
,控制台中的结果是
9
应该注意的是console
API是一个相当不稳定的准标准,并且因为它被设计为调试辅助,所以有一些行为可能令人困惑。然而,在这种情况下,它似乎只是简单地调用.toString()
而没有任何其他“有用”的有趣业务。但是,如果您只是将一个简单的空对象传递给console.log()
,就像这样
console.log({})
你得到(至少从Firefox中的Firebug)一个有用的界面来导航对象。如果您正在调试某些内容,那就太棒了,但是如果您正在尝试查看该语言的工作方式,那么这种行为可能会让您感到困惑。
作为最后一点,可以扩展已发布代码中的技巧,以便函数可以通过添加.valueOf()
方法来泄露数值结果:
function sum (a) {
var sum = a;
function f (b) {
sum += b;
return f;
}
f.toString = function () {
return sum;
};
f.valueOf = function() {
return sum;
};
return f;
}
如果你这样做,那么你会从
得到正确的答案console.log(2 * sum(4)(5))
答案 1 :(得分:3)
执行sum(4)(5)
时,首先执行sum(4)
,返回函数f
。
此函数可以访问变量sum
(由于JavaScript函数的闭包属性[1])。此函数执行求和并再次返回函数f
。
这一次console.log
正在尝试打印函数f
,因此我们通过定义f.toString
来打印总和,明确定义应该如何打印函数。
编辑:如果您想知道为什么只需添加两个数字就会感到非常痛苦,请尝试以下操作:
add(2)(1)(45)(22)
这是有效的,因为现在递归调用f
并且sum
被更新,这也是由于闭包属性。
1:即使父函数超出范围,内部函数也可以访问父函数的变量。