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
jsconst 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:
jsconst 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
elseclause
jsif (test) {return someValue;}// more complicated codereturn somethingElse;
- Ending an expression with a function declaration
jsreturn bounce(3, 2);function bounce(...) {}
- Avoiding polluting the global scope when using
vardeclarations
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:
jsreturn "Use this for the final value";
jsError: Syntax Error: Illegal return statement
To get around this you need to wrap your expression in a function and then call it, for example:
jsfunction 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