[英]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.