There are a lot of misconceptions about what an expression really is. An expression is not actually required to produce a value. Either that, or, at the very least, it’s debatable.
For example:
Is new Array(-1) an expression? Sure looks like it. It throws a RangeError.
JSON.parse("x") is an expression, right? It throws a SyntaxError.
These errors can be caught with try–catch.
What about (() => {await x})? It’s a function expression wrapping another expression with await. All the parts are expressions (can you argue otherwise?). But, because await is not used top-level in an async function, it throws a SyntaxError in any context during parsing (so cannot be caught). Similarly: (function({}){"use strict";}).
This opens the question what kind of semantics are even applicable for the term “expression”. Is an expression a runtime thing? A syntax thing? Is it a thing before parsing? Or after parsing?
The ECMAScript specification, interestingly, doesn’t even define what an “expression” is in natural language. Instead, it provides grammar productions for “Expression”, defining it inductively, starting with the comma operator. It moves the question of what an “Expression” is further and further into less abstract questions, until it reaches concrete terminal symbols. For example an “Expression” is either an “AssignmentExpression” or an “Expression”, followed by a ,, followed by another “AssignmentExpression”. Then, similarly “AssignmentExpression” is defined, and so on.
Whether something is an expression cannot be determined without the full context (as demonstrated in the article with blocks vs. objects) and without building an AST (e.g. with AST explorer) (JS currently has no way of reflecting its own AST). On a mental level it’s an “I know it when I see it” kind of thing.
You will see that it returns 18 but despite that you cannot use it as an expression or where JavaScript expects a value. It is weird because you’d expect statements not to return anything, since the return value is pretty much useless if you cannot use it. That’s JavaScript for you, weird.
That is… not how things work. That statement does not return anything. It’s not a “weird” thing of JavaScript that a value is shown. This is the output of a JavaScript REPL. This output isn’t a return value, it’s the value from the completion record produced by the given code snippet. This completion record can only be accessed by a REPL, and only its value and (indirectly) its state can be accessed with the eval function, but only after its completion (e.g. eval("if(true){4;}") === 4, and if it doesn’t throw its state is “normal”). Also see Why does this do–while loop repeat the last value after the end?.
So whatever is returned by the block statement, is implicitly coerced to 0 used as the operand.
No. There is no second operand on the left, there is no return value of the block, there is no 0. This is neither a binary + nor a binary -. It’s unary+ and unary-.
For further actions, you may consider blocking this person and/or reporting abuse
We're a place where coders share, stay up-to-date and grow their careers.
There are a lot of misconceptions about what an expression really is. An expression is not actually required to produce a value. Either that, or, at the very least, it’s debatable.
For example:
Is
new Array(-1)
an expression? Sure looks like it. It throws aRangeError
.JSON.parse("x")
is an expression, right? It throws aSyntaxError
.These errors can be caught with
try
–catch
.What about
(() => {await x})
? It’s a function expression wrapping another expression withawait
. All the parts are expressions (can you argue otherwise?). But, becauseawait
is not used top-level in anasync
function, it throws a SyntaxError in any context during parsing (so cannot be caught). Similarly:(function({}){"use strict";})
.This opens the question what kind of semantics are even applicable for the term “expression”. Is an expression a runtime thing? A syntax thing? Is it a thing before parsing? Or after parsing?
The ECMAScript specification, interestingly, doesn’t even define what an “expression” is in natural language. Instead, it provides grammar productions for “
Expression
”, defining it inductively, starting with the comma operator. It moves the question of what an “Expression
” is further and further into less abstract questions, until it reaches concrete terminal symbols. For example an “Expression
” is either an “AssignmentExpression
” or an “Expression
”, followed by a,
, followed by another “AssignmentExpression
”. Then, similarly “AssignmentExpression
” is defined, and so on.Whether something is an expression cannot be determined without the full context (as demonstrated in the article with blocks vs. objects) and without building an AST (e.g. with AST explorer) (JS currently has no way of reflecting its own AST). On a mental level it’s an “I know it when I see it” kind of thing.
That is… not how things work. That statement does not return anything. It’s not a “weird” thing of JavaScript that a value is shown. This is the output of a JavaScript REPL. This output isn’t a return value, it’s the value from the completion record produced by the given code snippet. This completion record can only be accessed by a REPL, and only its value and (indirectly) its state can be accessed with the
eval
function, but only after its completion (e.g.eval("if(true){4;}") === 4
, and if it doesn’t throw its state is “normal”). Also see Why does thisdo
–while
loop repeat the last value after the end?.No. There is no second operand on the left, there is no return value of the block, there is no
0
. This is neither a binary+
nor a binary-
. It’s unary+
and unary-
.