I know the typical form of an IIFE is:
(function(){/* code */})()
However, recently I found a new one:
!function(){/* code */}()
+function(){/* code */}()
which also work as IIFEs.
I think in the first !
makes the value a boolean, so the code is equivalent to true()
, and in the second +
makes the value a number, so the code is the same as NaN()
? But true()
and NaN()
cannot possibly work, while the above two forms work well.
How do those two forms of IIFE work?
In the cases of !function() {}()
and +function() {}()
JavaScript will first evaluate the right handside of the given statement/IIFE and then cast the return value of the IIFE to a boolean in case of !
or to type number in case of +
.
If the IIFE returns a boolean !
will negate the return value.
console.log(
!function() {
return "something";
}()
);
/**
!function() {
return "something";
}()
evaluates to
!"something" and not true() or false()
lastly !"something" is equivalent to false
*/
There are many ways to get a function to execute immediately upon its definition. The common thing is that you must make sure the function is not interpreted as a function statement, but as a function expression.
By prefixing the function keyword with a unary operator like !
or +
or any other unary operator (~
, -
, void
, ...etc) you avoid that the function
is interpreted as a statement.
Also assignment will work:
var x = function(){/* code */}()
Or array literal:
[function(){/* code */}()]
Or passing it as argument to a (cheap) function:
Object(function(){/* code */}())
Or applying a binary operator, provided the function expression is the second operand and not the first. Here with the comma operator:
0,function(){/* code */}()
The function
keyword has a duel purpose. Depending on the context you use it in, it either starts a function declaration or a function expression.
Function declarations declare a (hoisted) local variable in the scope of the current function and assign the function to that variable.
Function expressions don't, they require that you do something with the function immediately. Common examples include assigning it to a property of an object, passing it as an argument to a function (i.e. making it a callback) or using it as an IIFE.
If you try to follow a function declaration with ()
then it will error.
function myFunction() {
console.log("Example");
}();
Only function expressions can be immediately invoked function expressions. (Well, arrow functions can too, but IIFEs are much older than them).
So to use an IIFE you have to do something to change the context the function
keyword appears in so it is used to create an expression instead of a declaration.
The classic way is to wrap the function in parentheses.
(function myFunction() {
console.log("Example");
})();
But anything that makes it an expression will work.
Putting an operator (such as !
or +
) in front of the function
keyword will do that.
While !
will take the return value of calling the IIFE and turn it into a negated boolean and +
will turn it into a number that isn't the point. There's nothing to the left hand side of the operator so that value is discarded.
It is just a way to make the function
keyword create a function expression that can be turned into an IIFE.
Note that the key benefits of IIFEs are also provided by block scoped variables (let
and const
) and JavaScript modules, so there isn't much reason to use an IIFE at all in 2022.