Statements and expressions are different language units. What's probably tripping you up is that JavaScript, unlike some other languages, has what the spec calls ExpressionStatement: It can treat any expression as a statement (but it cannot treat statements as expressions). So for instance, this is valid JavaScript:
flag && console.log("Hi there");
...whereas in (say) Java that wouldn't be valid, because while Java has some specific statements to allow for specific expression-like things (method calls, for instance), it doesn't have JavaScript's overall ExpressionStatement.
Why void
transform this:
void function() {
}();
into an expression?
Because void
is an operator. It evaluates its operand (whatever follows it), and then sets its result to undefined
. It's not at all related to the void
that you see in languages like C, C++, Java, or C#. So the whole thing is an ExpressionStatement. The only reason you need the void
there is that without it, when the parser is expecting to see a statement, the keyword function
puts the parser into a state where it's expecting a function declaration, not an expression. (You can use any operator, not just void
, to put the parser into expression state; details in this question and its answers.)
And why this works:
something((something) => something + 2);
and this don't:
something((something) => if (something) { something + 2 });
Because of the way arrow functions are defined by the specification. There are two forms of arrow function:
- Ones with a concise body (no
{}
)
- Ones with a verbose body
Concise example:
array.sort((a, b) => a - b);
Equivalent verbose example:
array.sort((a, b) => {
return a - b;
});
Arrow functions with concise bodies require that the body be an expression because, as you can see above, they return the result of the expression. You can't use a statement there for the same reason you can't use a statement other places an expression is required: A result value is needed for the implicit return
statement. Your second example, translated to a verbose body, is this:
something((something) => {
return if (something) { something + 2 };
});
...which demonstrates why it didn't work: You have an if
after return
, but the return
statement requires an operand (expression) or statement terminator instead.
if
isn't a function, and has no return value, therefore you cannot assign the "result" of anif
to something, becauseif
HAS NO results. – Aeolic