1)为什么JavaScript中存在这种不一致 - 我期待第四行也返回11:
(function(n, m) { n = n + m; return n })(3, 8) == 11
(function(n, m) { var n = n + m; return n })(3, 8) == 11
(function(n) { return function(m) { n = n + m; return n } })(3)(8) == 11
(function(n) { return function(m) { var n = n + m; return n } })(3)(8) == NaN
2)我正在为javascript编写一种语言编译器。我使用var
来避免使用临时变量污染全局空间。它恰好发生在我的临时变量n
以上,并且压倒一切正常
还有另一种方法可以(重新)定义n
,这样如果先前没有定义n,它仍然认为n
是本地的吗?
以下两个变体使用tmp
污染了命名空间,我想避免这种情况:
(function(n, m) { tmp = n + m; return tmp })(3, 8) == 11
(function(n) { return function(m) { tmp = n + m; return tmp } })(3)(8) == 11
答案 0 :(得分:10)
在你的第四个例子中:
(function(n) { return function(m) { var n = n + m; return n } })(3)(8) // == NaN
...您已使用本地声明阴影外部函数的n
参数。由于您没有给出局部变量任何初始值设定项,因此其默认值为undefined
。 undefined
加上任何数字都是NaN
。
您可能想知道为什么这与您的第二个示例不同:
(function(n, m) { var n = n + m; return n })(3, 8) // == 11
答案是范围。在第二个示例中,var n
出现在n
参数已存在的范围内,因此不会影响它(使用var
与同一范围内的参数具有相同的标识符是无操作的)。但在第四个示例中,var n
出现在参数n
所在的嵌套范围内。因此它遮蔽了父n
。
此处var
没有做任何事情,因为已经有n
范围内的内容:
function foo(n) {
var n;
console.log(n);
}
foo(42); // 42

但在这里,确实如此:
function foo(n) {
(function() {
var n;
console.log(n);
})();
}
foo(42); // undefined

...因为参数和var
在不同的范围内。
以下两个变体使用tmp污染命名空间,我想避免使用
不需要tmp
(虽然本地 tmp
会没问题)。如果您想要嵌套功能,请不要在var
上使用n
:
console.log(
(function(n) { return function(m) { n = n + m; return n } })(3)(8) // == NaN
);

也就是说,本地 tmp
(使用var
)并不是坏事:
console.log(
(function(n) { return function(m) {
var tmp = n + m;
return tmp;
}})(3)(8) // == 11
);

...但你必须申报。如果没有var
声明它,代码将成为The Horror of Implicit Globals *的牺牲品,您确实希望避免这种情况。 : - )
* (这是我贫穷的小博客上的帖子)
答案 1 :(得分:-1)
将var
放在内部函数的n
前面,您将声明一个新的n
变量,此时此变量为undefined
并且是您的原因得到NaN
(例如undefined
+ 8 = NaN
)。
无需声明新变量。只需返回值:
(function(n) {
return function(m) {
return n + m;
}
})(3)(8)