I'am studying the behaviour of Immediatly Invoked Function Expressions (IIFE) and while doing that I encounterd the following situation.
(function () {
document.write("bar");
})
(function () {
document.write("foo");
}());
I thought that the first is just a grouping operator with a function expression inside without calling it. The second is a grouping operator as well with a function expression but now with the call of that function.
What I find strange is that both are invoked, why is that?
(function () {
document.write("bar");
})
var x = 1;
(function () {
document.write("foo");
}());
When I break the two by inserting a variable declaration in between, it's just writes foo. This is what I expected.
Because you forgot the semicolon after the first function expression:
(function () {
document.write("bar");
});
Otherwise the second "grouping operator" is interpreted as a function call. So this:
(function a() {
...
})
(function b() {
...
}());
is basically the same as:
function b() {
...
}
(function a() {
...
})(b());
Reordering makes it a bit easier to see. Remember that white space characters have no meaning in JavaScript and are ignored.
As Felix Kling correctly noted: the missing semicolon causes the parentheses around the second IIFE to be interpreted as a function call rather than just grouping the function expression. It becomes much more clear without the newlines:
(function () {
document.write("bar");
})(function () {
document.write("foo");
}());
Or with some realignment:
(function () {
document.write("bar");
})(
function () {
document.write("foo");
}()
);
The first function expression is called with the result of the second function expression as its first and only argument. You should also note that foobar
is written rather than barfoo
, as the second function is called first and its result is passed as an argument to the first function.
You can write a IIFE also like that: (function () {})()
By omitting the semicolon, your first codesnippet actually calls the first function with the second IIFE handed over as parameter for the first.
executing as parameter for the first IIFE
\/
(function () {document.write("bar");})( (function () {document.write("foo");}());)
which first prints foo
and then bar
unlike:
(function () {
document.write("bar");
})();
(function () {
document.write("foo");
}());
which prints barfoo
or
(function () {
document.write("bar");
});
(function () {
document.write("foo");
}());
where the first now is solely considered as grouping operator.