Javascript闭包:变量的重用不一致

时间:2017-12-22 21:40:44

标签: javascript closures

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

2 个答案:

答案 0 :(得分:10)

在你的第四个例子中:

(function(n) { return function(m) { var n = n + m; return n } })(3)(8) // == NaN

...您已使用本地声明阴影外部函数的n参数。由于您没有给出局部变量任何初始值设定项,因此其默认值为undefinedundefined加上任何数字都是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)