【问题标题】:Javascript closure unexpected resultJavascript关闭意外结果
【发布时间】:2014-04-09 10:38:09
【问题描述】:

闭包代码很短:

var fn = function() {
    return function() {
        console.log(arguments);
    }
}

(function(arg) {
    console.log('bar');
})('foo');

为什么打印的是["foo"] 而不是bar?如果我注释掉 var fn = ... ,结果与预期一致,并打印 bar 。这两段代码怎么关联?

【问题讨论】:

  • 看看代码有多漂亮!我喜欢它
  • 既然您的问题已经得到解答,请考虑以下难题:var a = d * e NEWLINE (d + e).blah() NEWLINE (1) 分号插入到哪里? (2) 你能提供在这个片段之前运行的代码吗?您的示例和此示例说明了为什么自动半插入首先是一个坏主意。它将编译器立即检测到的一个小而容易修复的编程错误变成了一系列陷阱,这些陷阱会通过意外更改程序的含义来困住粗心的程序员。
  • 这几乎看起来像是一次拖钓尝试。这是您自己写的还是在某个地方找到的?

标签: javascript


【解决方案1】:

如果fn} 后面没有分号,您实际上是在调用带有参数(function...)fn

如果添加缺少的分号,它会按预期工作:

var fn = function () {
    return function () {
        console.log(arguments);
    }
};

(function (arg) {
    console.log('bar');
})('foo');

【讨论】:

  • 一个缩小的例子是(function() { return function() { console.log(arguments); }})()('foo'),它也产生foo
  • 是的,正如我所说,没有分号,虽然格式不明显,但第二部分实际上是与第一部分连接的。
  • 我同意你说的 - 我只是添加它以供参考。这不是一个答案,所以正确的答案是添加它的最佳位置。 :-)
  • 是的,当然,我只是想指出,在这种情况下,格式是发生事情的罪魁祸首。他可能认为这两个部分是无关的,因为格式。
  • 实际上他并没有调用fn,而是将两次调用的结果分配给它(undefined)。
【解决方案2】:

为什么打印的是["foo"] 而不是'bar'?这两段代码怎么关联?

(function(arg) {…}) 周围有括号,它被视为函数表达式的参数,正如您期望 ('foo') 是 IEFE 的参数一样。实际上,foo 现在被传递给作为第一次调用结果的函数:

var fn = (
        (function() {
            return function() {
                console.log(arguments);
            };
        })
        (function(arg) {
            console.log('bar');
        })
    )
    ('foo');

要解决此问题,请始终在分配后放置分号,或使用函数声明:

function fn() {
    return function() {
        console.log(arguments);
    }
}
(function(arg) {
    console.log('bar');
})('foo');

【讨论】:

    【解决方案3】:

    在变量定义后添加分号,如下所示:

    var fn = function() {
        return function() {
            console.log(arguments);
        }
    };
    
    (function(arg) {
        console.log('bar');
    })('foo');
    

    记录“栏”。

    【讨论】:

    • 这并不能真正回答“为什么”这个问题。