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

Mik*_*yer 1 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
Run Code Online (Sandbox Code Playgroud)

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
Run Code Online (Sandbox Code Playgroud)

T.J*_*der 10

在你的第四个例子中:

(function(n) { return function(m) { var n = n + m; return n } })(3)(8) // == NaN
Run Code Online (Sandbox Code Playgroud)

...你用本地声明掩盖n外部函数的参数.由于您没有为任何初始化程序提供该局部变量,因此其默认值为undefined.undefined加上任何数字都是NaN.

您可能想知道为什么这与您的第二个示例不同:

(function(n, m) { var n = n + m; return n })(3, 8) // == 11
Run Code Online (Sandbox Code Playgroud)

答案是范围.在第二个示例中,var n出现在n参数已存在的范围内,因此不会影响它(使用var与同一范围内的参数相同的标识符是无操作).但是在第四个示例中,var n出现在参数存在的范围下的嵌套范围中n.所以它影响了父母n.

在这里,var它没有做任何事情,因为已经有一个n范围内:

function foo(n) {
    var n;
    console.log(n);
}
foo(42); // 42
Run Code Online (Sandbox Code Playgroud)

但在这里,它确实:

function foo(n) {
    (function() {
        var n;
        console.log(n);
    })();
}
foo(42); // undefined
Run Code Online (Sandbox Code Playgroud)

...因为参数和var范围不同.

以下两个变体用tmp污染命名空间,我想避免使用它

没必要tmp(虽然当地人 tmp会没事).如果你想要一个嵌套函数,就不要使用varon n:

console.log(
    (function(n) { return function(m) { n = n + m; return n } })(3)(8) // == NaN
);
Run Code Online (Sandbox Code Playgroud)

也就是说,本地 tmp(使用var)不会是坏事:

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

......但你必须申报.如果没有var声明它,代码将成为隐含全球恐怖*的牺牲品,你确实想要避免它.:-)


*(这是我贫血的小博客上的帖子)