- Statements and declarations
- Statements and declarations by category
- Control flow
- Declaring variables
- Functions and classes
- Iterations
- Others
- Difference between statements and declarations
- Browser compatibility
- See also
- Found a content problem with this page?
- MDN
- Support
- Our communities
- Developers
- Statements Vs. Expressions
- Expressions versus statements in JavaScript
- Statements and expressions
- Similar kinds of statements and expressions
- If statement versus conditional operator
- Semicolon versus comma operator
- Expressions that look like statements
- Object literal versus block
- Function expression versus function declaration
- Using object literals and function expressions as statements
- eval
- Immediately invoked function expressions (IIFEs)
- Concatenating IIFEs
- Related posts
Statements and declarations
JavaScript applications consist of statements with an appropriate syntax. A single statement may span multiple lines. Multiple statements may occur on a single line if each statement is separated by a semicolon. This isn’t a keyword, but a group of keywords.
Statements and declarations by category
For an alphabetical listing see the sidebar on the left.
Control flow
Specifies the value to be returned by a function.
Terminates the current loop, switch, or label statement and transfers program control to the statement following the terminated statement.
Terminates execution of the statements in the current iteration of the current or labeled loop, and continues execution of the loop with the next iteration.
Throws a user-defined exception.
Executes a statement if a specified condition is true. If the condition is false, another statement can be executed.
Evaluates an expression, matching the expression’s value to a case clause, and executes statements associated with that case.
Marks a block of statements to try, and specifies a response, should an exception be thrown.
Declaring variables
Declares a variable, optionally initializing it to a value.
Declares a block scope local variable, optionally initializing it to a value.
Declares a read-only named constant.
Functions and classes
Declares a function with the specified parameters.
Generator Functions enable writing iterators more easily.
Declares an async function with the specified parameters.
Asynchronous Generator Functions enable writing async iterators more easily.
Iterations
Creates a loop that executes a specified statement until the test condition evaluates to false. The condition is evaluated after executing the statement, resulting in the specified statement executing at least once.
Creates a loop that consists of three optional expressions, enclosed in parentheses and separated by semicolons, followed by a statement executed in the loop.
Iterates over the enumerable properties of an object, in arbitrary order. For each distinct property, statements can be executed.
Iterates over iterable objects (including arrays, array-like objects, iterators and generators), invoking a custom iteration hook with statements to be executed for the value of each distinct property.
Iterates over async iterable objects, array-like objects, iterators and generators, invoking a custom iteration hook with statements to be executed for the value of each distinct property.
Creates a loop that executes a specified statement as long as the test condition evaluates to true. The condition is evaluated before executing the statement.
Others
An empty statement is used to provide no statement, although the JavaScript syntax would expect one.
A block statement is used to group zero or more statements. The block is delimited by a pair of curly brackets.
An expression statement evaluates an expression and discards its result. It allows the expression to perform side effects, such as executing a function or updating a variable.
Invokes any available debugging functionality. If no debugging functionality is available, this statement has no effect.
Used to export functions to make them available for imports in external modules, and other scripts.
Used to import functions exported from an external module, another script.
Provides a statement with an identifier that you can refer to using a break or continue statement.
Extends the scope chain for a statement.
Difference between statements and declarations
In this section, we will be mixing two kinds of constructs: statements and declarations. They are two disjoint sets of grammars. The following are declarations:
- let
- const
- function
- function*
- async function
- async function*
- class
- export (Note: it can only appear at the top-level of a module)
- import (Note: it can only appear at the top-level of a module)
Everything else in the list above is a statement.
The terms «statement» and «declaration» have a precise meaning in the formal syntax of JavaScript that affects where they may be placed in code. For example, in most control-flow structures, the body only accepts statements — such as the two arms of an if. else :
if (condition) statement1; else statement2;
If you use a declaration instead of a statement, it would be a SyntaxError . For example, a let declaration is not a statement, so you can’t use it in its bare form as the body of an if statement.
if (condition) let i = 0; // SyntaxError: Lexical declaration cannot appear in a single-statement context
On the other hand, var is a statement, so you can use it on its own as the if body.
You can see declarations as «binding identifiers to values», and statements as «carrying out actions». The fact that var is a statement instead of a declaration is a special case, because it doesn’t follow normal lexical scoping rules and may create side effects — in the form of creating global variables, mutating existing var -defined variables, and defining variables that are visible outside of its block (because var -defined variables aren’t block-scoped).
As another example, labels can only be attached to statements.
label: const a = 1; // SyntaxError: Lexical declaration cannot appear in a single-statement context
Note: there’s a legacy grammar that allows function declarations to have labels, but it’s only standardized for compatibility with web reality.
To get around this, you can wrap the declaration in braces — this makes it part of a block statement.
label: const a = 1; > if (condition) let i = 0; >
Browser compatibility
BCD tables only load in the browser
See also
Found a content problem with this page?
This page was last modified on Jul 3, 2023 by MDN contributors.
Your blueprint for a better internet.
MDN
Support
Our communities
Developers
Visit Mozilla Corporation’s not-for-profit parent, the Mozilla Foundation.
Portions of this content are ©1998– 2023 by individual mozilla.org contributors. Content available under a Creative Commons license.
Statements Vs. Expressions
So, a few years ago, I was teaching web development at a local coding bootcamp, and a student asked me this question:
What’s the difference between a “statement” and an “expression” in JavaScript?
I felt like I knew the answer to this question, but when I tried to explain it, I couldn’t put it into words. I had a feeling about it, but my actual knowledge was surprisingly hazy.
There’s nothing more humbling than teaching 😅. Students have a knack for identifying the «fuzzy spots» in our understanding.
I’ve since come to realize that this question is supremely important. It’s a load-bearing concrete pillar that will help support a ton of JavaScript knowledge.
This is especially true for React developers. Most of those JSX rules you’ve had to memorize, and always forget to follow, are the result of this statement/expression duality.
In this blog post, I’m going to share some of the epiphanies I’ve had about this distinction, and how we can use this information in our day-to-day work.
This tutorial assumes that you’re comfortable with basic JavaScript syntax, but is otherwise written to be beginner-friendly. Towards the end of the tutorial, we look at some React implications, and this section requires some React experience. If you’re not a React dev, feel free to skip this section; hopefully, the rest of the tutorial will still offer a ton of value!
Expressions versus statements in JavaScript
This blog post looks at a syntactic distinction that is unfortunately quite important in JavaScript: the difference between expressions and statements.
Statements and expressions
JavaScript distinguishes expressions and statements. An expression produces a value and can be written wherever a value is expected, for example as an argument in a function call. Each of the following lines contains an expression:
Roughly, a statement performs an action. Loops and if statements are examples of statements. A program is basically a sequence of statements (we’re ignoring declarations here). Wherever JavaScript expects a statement, you can also write an expression. Such a statement is called an expression statement. The reverse does not hold: you cannot write a statement where JavaScript expects an expression. For example, an if statement cannot become the argument of a function.
Similar kinds of statements and expressions
The difference between statements and expressions becomes clearer if we look at members of the two syntactic categories that are similar.
If statement versus conditional operator
Expressions have an analog, the conditional operator. The above statements are equivalent to the following statement.
The code between the equals sign and the semicolon is an expression. The parentheses are not necessary, but I find the conditional operator easier to read if I put it in parens.
Semicolon versus comma operator
> "a", "b" 'b' > var x = ("a", "b"); > x 'b' > console.log(("a", "b")); b
Expressions that look like statements
Some expressions look like statements. We’ll examine why that is a problem at the end of this section.
Object literal versus block
- A block: a sequence of statements in curly braces.
- A label: you can prefix any statement with a label. Here the label is foo.
- A statement: the expression statement bar(3, 5).
Given that the plus operator is commutative, shouldn’t these two (expression) statements return the same result? No, because the second statement is equivalent to a code block followed by +[]:
JavaScript has stand-alone blocks? It might surprise you that JavaScript has blocks that can exist on their own (as opposed to being part of a loop or an if statement). The following code illustrates one use case for such blocks: You can give them a label and break from them.
function test(printTwo) < printing: < console.log("One"); if (!printTwo) break printing; console.log("Two"); >console.log("Three"); >
> test(false) One Three > test(true) One Two Three
Function expression versus function declaration
The function name (foo, above) only exists inside the function and can, for example, be used for self-recursion:
> var fac = function me(x) < return x > fac(10) 3628800 > console.log(me) ReferenceError: me is not defined
A named function expression is indistinguishable from a function declaration (which is, roughly, a statement). But their effects are different: A function expression produces a value (the function). A function declaration leads to an action – the creation of a variable whose value is the function. Furthermore, only a function expression can be immediately invoked, but not a function declaration.
Using object literals and function expressions as statements
We have seen that some expressions are indistinguishable from statements. That means that the same code works differently depending on whether it appears in an expression context or a statement context. Normally the two contexts are clearly separated. However, with expression statements, there is an overlap: There, you have expressions that appear in a statement context. In order to prevent ambiguity, the JavaScript grammar forbids expression statements to start with a curly brace or with the keyword function:
ExpressionStatement : [lookahead ∉ ] Expression ;
So what do you do if you want to write an expression statement that starts with either of those two tokens? You can put it in parentheses, which does not change its result, but ensures that it appears in an expression-only context. Let’s look at two examples: eval and immediately invoked function expressions.
eval
eval parses its argument in statement context. If you want eval to return an object, you have to put parentheses around an object literal.
Immediately invoked function expressions (IIFEs)
> function () < return "abc" >() SyntaxError: function statement requires a name
> function foo() < return "abc" >() SyntaxError: syntax error
Another way of guaranteeing that an expression is parsed in expression context is a unary operator such as + or !. But, in contrast to parentheses, these operators change the result of the expression. Which is OK, if you don’t need it:
NaN is the result of applying + to undefined, the result of calling the function. Brandon Benvie mentions another unary operator that you can use: void [2]:
> void function () < console.log("hello") >() hello undefined
Concatenating IIFEs
(function () <>()) (function () <>()) // TypeError: undefined is not a function
This code produces an error, because JavaScript thinks that the second line is an attempt to call the result of the first line as a function. The fix is to add a semicolon:
(function () <>()); (function () <>()) // OK
With operators that are only unary (plus is both unary and binary), you can omit the semicolon, because automatic semicolon insertion kicks in.
void function () <>() void function () <>() // OK
JavaScript inserts a semicolon after the first line, because void is not a valid way of continuing this statement [3].