Why is this grouping operator + function immediately invoked
Asked Answered
T

3

10

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.

Triable answered 11/2, 2013 at 11:4 Comment(1)
Tip: use jshint.comNordstrom
P
16

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.

Pru answered 11/2, 2013 at 11:6 Comment(0)
J
4

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.

Jehad answered 11/2, 2013 at 11:10 Comment(0)
C
3

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.

Cavalier answered 11/2, 2013 at 11:10 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.