我正在研究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。这就是我的预期。
答案 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");
}());
其中第一个现在仅被视为分组运算符。