10

我正在研究立即调用函数表达式 (IIFE) 的行为,在此过程中我遇到了以下情况。

(function () {
    document.write("bar");
})

(function () {
    document.write("foo");
}());

我认为第一个只是一个分组运算符,里面有一个函数表达式,没有调用它。第二个是分组运算符以及函数表达式,但现在调用该函数。

我觉得奇怪的是两者都被调用了,这是为什么呢?

(function () {
    document.write("bar");
})

var x = 1;

(function () {
    document.write("foo");
}());

当我通过在两者之间插入一个变量声明来打破这两者时,它只是写了 foo. 这是我所期望的。

4

3 回答 3

16

因为您忘记了第一个函数表达式后的分号:

(function () {
    document.write("bar");
});

否则,第二个“分组运算符”被解释为函数调用。所以这:

(function a() {
    ...
})

(function b() {
    ...
}());

基本上是一样的:

function b() {
    ...
}

(function a() {
    ...
})(b());

重新排序使它更容易看到。请记住,空白字符在 JavaScript 中没有任何意义,并且会被忽略。

于 2013-02-11T11:06:50.787 回答
4

正如 Felix Kling 正确指出的那样:缺少的分号导致第二个 IIFE 周围的括号被解释为函数调用,而不仅仅是对函数表达式进行分组。没有换行符会变得更加清晰:

(function () {
    document.write("bar");
})(function () {
    document.write("foo");
}());

或进行一些调整:

(function () {
    document.write("bar");
})(
    function () {
        document.write("foo");
    }()
);

第一个函数表达式被调用,第二个函数表达式的结果作为它的第一个也是唯一的参数。您还应该注意foobar是写而不是barfoo,因为第二个函数首先被调用,其结果作为参数传递给第一个函数。

于 2013-02-11T11:10:40.097 回答
3

你也可以这样写一个 IIFE:(function () {})()

通过省略分号,您的第一个代码片段实际上调用了第一个函数,第二个 IIFE 作为第一个的参数传递。

                    executing as parameter for the first IIFE
                                               \/ 
(function () {document.write("bar");})( (function () {document.write("foo");}());)

首先打印foo,然后bar不同于:

(function () {
    document.write("bar");
})();

(function () {
    document.write("foo");
}());

打印barfoo

(function () {
    document.write("bar");
});

(function () {
    document.write("foo");
}());

其中第一个现在仅被视为分组运算符。

于 2013-02-11T11:10:54.467 回答