为什么立即调用此分组运算符+函数

时间:2013-02-11 11:04:18

标签: javascript iife

我正在研究Immediatly Invoked Function Expressions(IIFE)的行为,在这样做时我遇到了以下情况。

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

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

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

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

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

var x = 1;

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

当我通过在两者之间插入变量声明来打破两者时,它只是写入foo。这就是我的预期。

3 个答案:

答案 0 :(得分:15)

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

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

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

(function a() {
    ...
})

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

基本上与:

相同
function b() {
    ...
}

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

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

答案 1 :(得分:4)

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

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

或者进行一些调整:

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

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

答案 2 :(得分:3)

您也可以像这样编写IIFE:(function () {})()

通过省略分号,您的第一个codenippet实际上调用第一个函数,第二个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");
}());

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