nCardot
nCardot

Reputation: 6585

In JavaScript, are all expressions statements?

So, my understanding is that the distinction between a statement and an expression is that a statement is a line of code that performs some action, whereas an expression produces a value. Further, while it makes sense that not all statements are expressions because not all resolve to a value (as in the cases of if, while, and for), if an expression produces a value, isn't that considered doing something, and therefore also a statement?

Upvotes: 3

Views: 282

Answers (2)

Bergi
Bergi

Reputation: 664620

The distinction between statements and expressions is mainly a grammatical one, i.e. they are terms used in the description of the parsing rules.

It only matters in which syntactical contexts they are valid. No, an expression is never the same thing as a statement.

Traditionally, statements describe units of code that are executed one after the other and written one below the other - that's where your "line of code" comes from. They do things like declaring functions and variables or being responsible for control flow. They are typically organised in (nested) blocks, delimited by curly braces in JavaScript.

Expressions on the other hand are units of code that produce a value from evaluating operators, often without doing anything - e.g. the expression 2 + 3 can be evaluated to the value 5, but nothing happens to that value. Expressions can be arbitrarily nested, with other expressions forming the operands of an operator.

Various languages define different things as statements and expressions, as there are no intrinsic differences but rather some interesing similarities - they can be nested, there are rules (on types) to be enforced and so on - and so assignments or if-conditions could be a statement in one language and an expression in another language (with blocks being just another type with its own operators and evaluation rules).

For JavaScript, the rules are detailed in the specification, and it does clearly distinguish statements from expressions. There is a little ambiguity though, as there is the expression statement, which is a statement that consists solely of an expression (to be evaluated) and a trailing semicolon - however the semicolon is optional. Still, it's a statement that contains an expression, it's not one thing that is both a statement and an expression.

Through this there are some code parts that would be valid as both, and you cannot tell the difference without looking at the context.

Upvotes: 2

Drew Noakes
Drew Noakes

Reputation: 310987

Since you asked the question tagged with computer-science as well as javascript I thought I'd point out that JavaScript is different to several other popular languages in this regard.

For example, in Java and C# you cannot use an arithmetic expression as a statement.

public class C {
    public void M() {
        1 + 2;
    }
}

The C# compiler rejects this code with message:

error CS0201: Only assignment, call, increment, decrement, and new object expressions can be used as a statement

A similar error is produced by the Java compiler:

error: not a statement

Such an expression has no observable effect in code, therefore computing it is pointless. The compiler designers chose to flag this as a compile error, presumably to help developers avoid a class of mistakes in their code.

Kotlin produces a warning:

Warning: The expression is unused

The D compiler (dmd) produces:

Error: + has no effect in expression (1 + 2)

GCC 6.3 (both for C and C++) doesn't seem to complain (though it might do if you turn on -Wall or other extended warnings).

Swift also doesn't complain.

So although JavaScript permits such expressions as statements, I would argue that it's a weakness of the language specification rather than a strength. If the return value is not applied anywhere then it's a waste of computation (either at runtime, or at JIT time) and potentially hides a bug, such as a missing return statement.

One final note is that some compilers may be able to elide the expression if it can determine it has no side effects. As an example 1 + 2 + doSomething() cannot be completely removed if doSomething does anything observable (such as print to the screen or update shared state), however the preceding addition operations could be discarded.

Upvotes: 3

Related Questions