All our expressions are written for the newer JavaScript Expressions Engine

Blog

Why we wrap our expressions in IIFEs

Photo of Tim Haywood
Tim Haywood

|

February 15, 2021

It can be difficult to determine what the final value for an expression is, especially when:

  • It's more than a few lines long
  • You didn't write it (or you wrote it a while ago)
  • It doesn't have comments

For example, can you tell what value is set in the below example?

position

js
const myPosition = [960, 540];
myPosition * 2;
[0, 0];
const otherPosition = [500, 500];
js
[0, 0];

Knowing which value is set requires reading through and understanding the whole expression.

To learn more about what determines the final value for an expression, see our article on statement completion values.

Using a return statement

Ideally you would be able to use a return statement, as if the expression was the body of a function:

js
const myPosition = [960, 540];
myPosition * 2;
return [0, 0];
const otherPosition = [500, 500];
js
[0, 0];

Which has the benefit of explicitly setting what value is used, allowing you to scan an expression for the return keyword and work backwards from the final value.

You can learn more about return statements in our article on functions.

Other benefits

Using return statements has more benefits than just being explicit, for example:

  • Skipping code with early returns, without needing an else clause
js
if (test) {
return someValue;
}
// more complicated code
return somethingElse;
  • Ending an expression with a function declaration
js
return bounce(3, 2);
function bounce(...) {}
  • Avoiding polluting the global scope when using var declarations

Wrapping expressions in a function

Using a return statement in an expression will result in an error, as they aren't allowed outside of a function body:

js
return "Use this for the final value";
js
Error: Syntax Error: Illegal return statement

To get around this you need to wrap your expression in a function and then call it, for example:

js
function main() {
return "Hello from return";
}
main();
js
"Hello from return";

IIFEs

While this works well, you can reduce the amount of syntax needed by using an IIFE.

IIFE stands for Immediately Invoked Function Expression.

This is a method for invoking the function as soon as it's created, by:

  • Wrapping an anonymous function in parenthesis (())
  • Followed by another pair of parenthesis to call it

For example:

js
(function () {
return someValue;
})();

You make a function anonymous by omitting it's name, which normally comes after the function keyword.

You can then further reduce the amount of code by changing the function to an ES6 arrow function:

js
(() => {
return "Returned!";
})();
js
"Returned!";

This allows you to gain the benefits of using return statements in your expressions, with minimal syntactical overhead.

For example, the expression from the top of this post becomes:

js
(() => {
const myPosition = [960, 540];
myPosition * 2;
return [0, 0];
const otherPosition = [500, 500];
})();
js
[0, 0];

Where it's now clear what value is being used as the result of the expression.

This isn't something you need to do on every expression, but rather another technique to keep your expressions easy to read and understand.

While the examples in this post have been simple, the benefits are especially true when it comes to longer and more complicated expressions.

Blog

For enquiries contact us at hey@motiondeveloper.com