简体   繁体   English

Javascript闭包:变量重用不一致

[英]Javascript closure: Inconsistent reuse of variable

1) Why is there this inconsistency in JavaScript - I was expecting the fourth line to return 11 as well: 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) I'm writing a compiler of a language to javascript. 2)我正在写一种语言的JavaScript编译器。 I use var to avoid polluting the global space with temporary variables. 我使用var避免使用临时变量污染全局空间。 It just happened above that my temporary variable was n and the overriding was fine. 刚好在上面,我的临时变量为n ,并且重写很好。
Is there another way so that I can (re)define n such that if n was not defined previously, it still considers that n is local? 还有另一种方法可以使我(重新)定义n ,以便如果先前未定义n时,它仍然认为n是局部的?

The following two variants pollute the namespace with tmp , which I want to avoid: 以下两个变体使用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

In your fourth example: 在您的第四个示例中:

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

...you've shadowed the n parameter of the outer function with a local declaration. ...您已经用局部声明遮盖了外部函数的n参数。 Since you haven't given that local variable any initializer, its default value is undefined . 由于尚未为该局部变量提供任何初始化程序,因此其默认值为undefined undefined plus any number is NaN . undefined加上任何数字为NaN

You may be wondering why this is different from your second example: 您可能想知道为什么这与您的第二个示例不同:

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

The answer is scope . 答案是范围 In the second example, the var n appears in the scope where the n parameter already exists, and so does not shadow it (using var with the same identifier as a parameter in the same scope is a no-op). 在第二个示例中, var n出现在已经存在n参数的范围内,因此不会对其进行阴影处理(在同一范围内使用具有相同标识符的var作为参数是无操作)。 But in the fourth example, the var n appears in a nested scope under the one where the parameter n exists. 但是在第四个示例中, var n出现在嵌套范围内,位于参数n存在的范围内。 And so it shadows the parent n . 因此它遮蔽了父n

Here, the var doesn't do anything, because there's already an n in-scope: 在这里, var不做任何事情,因为已经有n个作用域了:

 function foo(n) { var n; console.log(n); } foo(42); // 42 

But here, it does: 但是在这里,它确实:

 function foo(n) { (function() { var n; console.log(n); })(); } foo(42); // undefined 

...because the parameter and the var are in different scopes. ...因为参数和var在不同的范围内。

The following two variants pollute the namespace with tmp, which I want to avoid 以下两个变体使用tmp污染了名称空间,我想避免

No need for tmp (although a local tmp would be fine). 不需要tmp (尽管可以使用本地 tmp )。 If you want a nested function, just don't use var on n : 如果您想使用嵌套函数,请不要在n上使用var

 console.log( (function(n) { return function(m) { n = n + m; return n } })(3)(8) // == NaN ); 

That said, a local tmp (using var ) would be no bad thing: 也就是说, 本地 tmp (使用var )不是一件坏事:

 console.log( (function(n) { return function(m) { var tmp = n + m; return tmp; }})(3)(8) // == 11 ); 

...but you have to declare it. ...但是您必须声明它。 Without the var declaring it, the code falls prey to The Horror of Implicit Globals *, which you do indeed want to avoid. 如果没有声明var ,则该代码将成为“隐式全局变量 * 的恐怖”的牺牲品,您确实希望避免这种情况。 :-) :-)


* (that's a post on my anemic little blog) * (这是我贫乏的小博客上的帖子)

By placing var in front of n in the inner function, you're declaring a new n variable, which at that point is undefined and the reason you're getting NaN (eg undefined + 8 = NaN ). 通过在内部函数中将var放在n前面,您将声明一个新的n变量,该变量在那时是undefined ,也是得到NaN的原因(例如, undefined + 8 = NaN )。

There's no need to declare a new variable. 无需声明新变量。 Just return the value: 只需返回值:

(function(n) {
  return function(m) {
    return n + m;
  }
})(3)(8)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM