Chapter 3 described expressions as JavaScript phrases. By that analogy, statements are JavaScript sentences or commands. Just as English sentences are terminated and separated from each other with periods, JavaScript statements are terminated with semicolons (Optional Semicolons). Expressions are evaluated to produce a value, but statements are executed to make something happen.
One way to âmake something happenâ is to evaluate an expression that has side effects. Expressions with side effects, such as assignments and function invocations, can stand alone as statements, and when used this way they are known as expression statements. A similar category of statements are the declaration statements that declare new variables and define new functions.
JavaScript programs are nothing more than a sequence of statements to execute. By default, the JavaScript interpreter executes these statements one after another in the order they are written. Another way to âmake something happenâ is to alter this default order of execution, and JavaScript has a number of statements or control structures that do just this:
Conditionals are statements like
if
andswitch
that make the JavaScript interpreter execute or skip other statements depending on the value of an expression.Loops are statements like
while
andfor
that execute other statements repetitively.Jumps are statements like
break
,return
, andthrow
that cause the interpreter to jump to another part of the program.
Table 4-1 summarizes JavaScript statement syntax, and the sections that follow it describe each statement in more detail.
Table 4-1. JavaScript statement syntax
The simplest kinds of statements in JavaScript are expressions that have side effects. This sort of statement was shown in Chapter 3. Assignment statements are one major category of expression statements. For example:
greeting = "Hello " + name; i *= 3;
The increment and decrement operators, ++
and --
, are related to
assignment statements. These have the side effect of changing a variable
value, just as if an assignment had been performed:
counter++;
The delete
operator has the
important side effect of deleting an object property. Thus, it is almost
always used as a statement, rather than as part of a larger
expression:
delete o.x;
Function calls are another major category of expression statements. For example:
alert(greeting); window.close();
These client-side function calls are expressions, but they have side effects that affect the web browser and are used here as statements.
A statement block combines multiple statements into a single compound statement. A statement block is simply a sequence of statements enclosed within curly braces. Thus, the following lines act as a single statement and can be used anywhere that JavaScript expects a single statement:
{ x = Math.PI; cx = Math.cos(x); console.log("cos(Ï) = " + cx); }
Combining statements into larger statement blocks is extremely
common in JavaScript programming. Just as expressions often contain
subexpressions, many JavaScript statements contain substatements. Formally,
JavaScript syntax usually allows a
single substatement. For example, the while
loop syntax
includes a single statement that serves as the body of the loop. Using a
statement block, you can place any number of statements within this single
allowed substatement.
A compound statement allows you to use multiple statements where JavaScript syntax expects a single statement. The empty statement is the opposite: it allows you to include no statements where one is expected.
The empty statement looks like this:
;
The JavaScript interpreter takes no action when it executes an empty statement. The empty statement is occasionally useful when you want to create a loop that has an empty body:
// Initialize the elements of a to 0 for(i = 0; i < a.length; a[i++] = 0) /* empty */;
The var
and function
are declaration
statementsâthey declare or define variables and functions.
These statements define identifiers (variable and function names) that can
be used elsewhere in your program and assign values to those identifiers.
Declaration statements donât do much themselves, but by creating variables
and functions they, in an important sense, define the meaning of the other statements
in your program.
The var
statement
declares a variable or variables. Hereâs the syntax:
varname_1
[ =value_1
] [ ,...,name_n
[=value_n
]]
The var
keyword is followed by
a comma-separated list of variables to declare; each variable in the
list may optionally have an initializer expression that specifies its
initial value. For example:
var i; // One simple variable var j = 0; // One var, one value var p, q; // Two variables var greeting = "hello" + name; // A complex initializer var x = 2, y = x*x; // Second var uses first var x = 2, // Multiple variables... f = function(x) { return x*x }, // each on its y = f(x); // own line
If a var
statement appears
within the body of a function, it defines local variables, scoped to
that function. When var
is used in
top-level code, it declares global variables, visible throughout the
JavaScript program.
If no initializer is specified for a variable with the var
statement, the variableâs initial value is
undefined
.
Note that the var
statement can
also appear as part of the for
and
for/in
loops:
for(var i = 0; i < 10; i++) console.log(i); for(var i = 0, j=10; i < 10; i++,j--) console.log(i*j); for(var i in o) console.log(i);
The function
keyword is
used to define functions. We saw it in function definition expressions
in Function Definition. It can also be used in statement
form. Consider the following two functions:
// Expression assigned to a variable var f = function(x) { return x+1; } // The statement form includes the variable name function f(x) { return x+1; }
A function declaration statement has the following syntax:
functionfuncname
([arg1
[,arg2
[...,argn
]]]) {statements
}
funcname
is an identifier that names
the function being declared. The function name is followed by a
comma-separated list of parameter names in parentheses. These
identifiers can be used within the body of the function to refer to the
argument values passed when the function is invoked.
The body of the function is composed of any number of JavaScript statements, contained within curly braces. These statements are not executed when the function is defined. Instead, they are associated with the new function object for execution when the function is invoked.
Here are some more examples of function declarations:
function hypotenuse(x, y) { return Math.sqrt(x*x + y*y); } function factorial(n) { // A recursive function if (n <= 1) return 1; return n * factorial(n - 1); }
Function declaration statements may appear in top-level JavaScript
code, or they may be nested within other functions. When nested,
however, function declarations may only appear at the top level of the
function they are nested within. That is, function definitions may not
appear within if
statements, while
loops, or any other
statements.
Function declaration statements differ from function definition
expressions in that they include a function name. Both forms create a
new function object, but the function declaration statement also
declares the function name as a variable and assigns the function object
to it. Like variables declared with var
, functions defined with function
definition statements are implicitly âhoistedâ to the top of the
containing script or function, so that all functions in a script or all
nested functions in a function are declared before any other code is
run. This means that you can invoke a JavaScript function before you
declare it.
Conditional statements execute or skip other statements depending on the value of a specified expression. These statements are the decision points of your code, and they are also sometimes known as âbranches.â If you imagine a JavaScript interpreter following a path through your code, the conditional statements are the places where the code branches into two or more paths and the interpreter must choose which path to follow.
The if
statement is the
fundamental control statement that allows JavaScript to execute
statements conditionally. This statement has two forms. The first
is:
if (expression
)statement
In this form, expression
is evaluated.
If the resulting value is truthy, statement
is executed. If expression
is falsy,
statement
is not executed:
if (username == null) // If username is null or undefined, username = "John Doe"; // define it
Note that the parentheses around the
expression
are a required part of the syntax
for the if
statement.
The second form of the if
statement introduces an else
clause
that is executed when expression
is false
. Its syntax is:
if (expression
)statement1
elsestatement2
This form of the statement executes
statement1
if
expression
is truthy and executes statement2
if
expression
is falsy. For example:
if (n == 1) { console.log("You have 1 new message."); } else { console.log("You have " + n + " new messages."); }
The if/else
statement
evaluates an expression and executes one of two pieces of code,
depending on the outcome. But what about when you need to execute one of
many pieces of code? One way to do this is with an else if
statement. else if
is not really a JavaScript statement,
but simply a frequently used programming idiom that results when
repeated if/else
statements are
used:
if (n == 1) { // Execute code block #1 } else if (n == 2) { // Execute code block #2 } else if (n == 3) { // Execute code block #3 } else { // If all else fails, execute block #4 }
There is nothing special about this code. It is just a series of
if
statements, where each following
if
is part of the else
clause of the previous statement. Using
the else if
idiom is preferable to,
and more legible than, writing these statements out in their
syntactically equivalent, fully nested form:
if (n == 1) { // Execute code block #1 } else { if (n == 2) { // Execute code block #2 } else { if (n == 3) { // Execute code block #3 } else { // If all else fails, execute block #4 } } }
An if
statement causes
a branch in the flow of a programâs execution, and you can use the
else if
idiom to perform a multiway
branch. This is not the best solution, however, when all of the branches
depend on the value of the same expression. In this case, it is wasteful
to repeatedly evaluate that expression in multiple if
statements.
The switch
statement handles
exactly this situation. The switch
keyword is followed by an expression in parentheses and a block of code
in curly braces:
switch(expression
) {statements
}
However, the full syntax of a switch
statement is more complex than this.
Various locations in the block of code are labeled with the case
keyword followed by an expression and a
colon. case
is like a labeled
statement, except that instead of giving the labeled statement a name,
it associates an expression with the statement. When a switch
executes, it computes the value of
expression
and then looks for a case
label whose expression evaluates to the
same value (where sameness is determined by the ===
operator). If it finds one, it starts
executing the block of code at the statement labeled by the case
. If it does not find a case
with a matching value, it looks for a
statement labeled default:
. If there
is no default:
label, the switch
statement skips the block of code
altogether.
The following switch
statement
is equivalent to the repeated if/else
statements shown in the previous section:
switch(n) { case 1: // Start here if n === 1 // Execute code block #1. break; // Stop here case 2: // Start here if n === 2 // Execute code block #2. break; // Stop here case 3: // Start here if n === 3 // Execute code block #3. break; // Stop here default: // If all else fails... // Execute code block #4. break; // stop here }
Note the break
keyword used at
the end of each case
in the code
above. The break
statement, described
later in this chapter, causes the interpreter to break out of the
switch
statement and continue with
the statement that follows it. The case
clauses in a switch
statement specify only the
starting point of the desired code; they do not
specify any ending point. In the absence of break
statements, a switch
statement begins executing its block of
code at the case
label that matches
the value of its expression
and continues
executing statements until it reaches the end of the block. Usually you
will want to end every case
with a
break
or return
statement.
Here is a more realistic example of the switch
statement; it converts a value to a
string in a way that depends on the type of the value:
function convert(x) { switch(typeof x) { case 'number': // Convert to a hexadecimal integer return x.toString(16); case 'string': // Enclose it in quotes return '"' + x + '"'; default: // Any other type return String(x); } }
Note that in the two previous examples, the case
keywords are followed by number and
string literals, respectively. This is how the switch
statement is most often used in
practice, but note that the ECMAScript standard allows each case
to be followed by an arbitrary
expression.
To understand conditional statements, we imagined the
JavaScript interpreter following a branching path through your source
code. The looping statements are those that bend that
path back upon itself to repeat portions of your code. JavaScript has four
looping statements: while
, do/while
, for
, and for/in
.
The while
statement is
JavaScriptâs basic loop. It has the following syntax:
while (expression
)statement
To execute a while
statement,
the interpreter first evaluates expression
.
If the value of the expression is falsy, then the interpreter skips over
the statement
that serves as the loop body
and moves on to the next statement in the program. If, on the other
hand, the expression
is truthy, the
interpreter executes the statement
and
repeats, jumping back to the top of the loop and evaluating
expression
again. Another way to say this is
that the interpreter executes statement
repeatedly while the
expression
is truthy. Note that you can
create an infinite loop with the syntax while(true)
.
Here is an example of a while
loop that prints the numbers from 0 to 9:
var count = 0; while (count < 10) { console.log(count); count++; }
As you can see, the variable count
starts off at 0 and is incremented each
time the body of the loop runs. Once the loop has executed 10 times, the
expression becomes false
(i.e., the
variable count
is no longer less than
10), the while
statement finishes,
and the interpreter can move on to the next statement in the
program.
The do/while
loop is
like a while
loop, except that the
loop expression is tested at the bottom of the loop rather than at the
top. This means that the body of the loop is always executed at least
once. The syntax of this relatively uncommon loop is:
dostatement
while (expression
);
Hereâs an example of a do/while
loop:
function printArray(a) { var len = a.length, i = 0; if (len == 0) console.log("Empty Array"); else { do { console.log(a[i]); } while (++i < len); } }
The for
statement
simplifies loops that follow a common pattern. Most loops have a counter
variable of some kind. This variable is initialized before the loop
starts and is tested before each iteration of the loop. Finally, the
counter variable is incremented or otherwise updated at the end of the
loop body, just before the variable is tested again. In this kind of
loop, the initialization, the test, and the update are the three crucial
manipulations of a loop variable. The for
statement encodes each of these three
manipulations as an expression and makes those expressions an explicit
part of the loop syntax:
for(initialize
;test
;increment
)statement
initialize
, test
, and increment
are three expressions
(separated by semicolons) that are responsible for initializing,
testing, and incrementing the loop variable. Putting them all in the
first line of the loop makes it easy to understand what a for
loop is doing and prevents mistakes such
as forgetting to initialize or increment the loop variable.
The simplest way to explain how a for
loop works is to show the equivalent
while
loop:
initialize
; while(test
) {statement
increment
; }
In other words, the initialize
expression is evaluated once, before the loop begins. To be useful, this
expression must have side effects (usually an assignment). JavaScript
also allows initialize
to be a var
variable declaration statement so that you
can declare and initialize a loop counter at the same time. The
test
expression is evaluated before each
iteration and controls whether the body of the loop is executed. If
test
evaluates to a truthy value, the
statement
that is the body of the loop is
executed. Finally, the increment
expression
is evaluated. Again, this must be an expression with side effects in
order to be useful. Generally, either it is an assignment expression, or
it uses the ++
or --
operators.
We can print the numbers from 0 to 9 with a for
loop like the following. Contrast it with
the equivalent while
loop shown
above:
for(var count = 0; count < 10; count++) console.log(count);
The for/in
statement
uses the for
keyword, but it is
a completely different kind of loop than the regular for
loop. A for/in
loop looks like this:
for (variable
inobject
)statement
variable
typically names a variable,
but it may also be a var
statement
that declares a single variable. object
is an
expression that evaluates to an object. As usual,
statement
is the statement or statement block
that serves as the body of the loop.
It is easy to use a regular for
loop to iterate through the elements of an array:
// Assign array indexes to variable i for(var i = 0; i < a.length; i++) console.log(a[i]); // Print each array element
The for/in
loop makes it easy
to do the same for the properties of an object:
// Assign property names of o to variable p for(var p in o) console.log(o[p]); // Print each property
To execute a for/in
statement,
the JavaScript interpreter first evaluates the
object
expression and then executes the body
of the loop once for each enumerable property of the resulting object.
Before each iteration, however, the interpreter assigns the name of the
property to the variable
.
The for/in
loop does not
actually enumerate all properties of an object, only the
enumerable properties (see Property Attributes). The various built-in methods defined
by core JavaScript are not enumerable. All objects have a toString()
method, for example, but the
for/in
loop does
not enumerate this toString
property.
In addition to built-in methods, many other properties of the built-in
objects are nonenumerable. All properties and methods defined by your
code are enumerable, however. (But in ECMAScript 5, you can make them
nonenumerable using techniques explained in Property Attributes.)
The ECMAScript specification does not describe the order
in which the for/in
loop enumerates
the properties of an object. In practice, however, JavaScript
implementations from all major browser vendors enumerate the properties
of simple objects in the order in which they were defined, with older
properties enumerated first. If an object was created as an object
literal, its enumeration order is the same order that the properties
appear in the literal. Note that this enumeration order does not apply
to all objects. In particular, if an object includes array index
properties, those properties may be enumerated in numeric order rather
than in creation order.
Another category of JavaScript statements are jump
statements. As the name implies, these cause the JavaScript
interpreter to jump to a new location in the source code. The break
statement makes the interpreter jump to
the end of a loop or other statement. continue
makes the interpreter skip the rest of
the body of a loop and jump back to the top of a loop to begin a new
iteration. JavaScript allows statements to be named, or
labeled, and the break
and continue
can identify the target loop or other
statement label. The return
statement
makes the interpreter jump from a function invocation back to the code
that invoked it and also supplies the value for the invocation. The
throw
statement raises, or âthrows,â an
exception and is designed to work with the try/catch/finally
statement, which establishes a
block of exception handling code.
Any statement may be labeled by preceding it with an identifier and a colon:
identifier
:statement
By labeling a statement, you give it a name that you can use to
refer to it elsewhere in your program. You can label any statement,
although it is only useful to label statements that have bodies, such as
loops and conditionals. By giving a loop a name, you can use break
and continue
statements inside the body of the
loop to exit the loop or to jump directly to the top of the loop to
begin the next iteration. break
and
continue
are the only JavaScript
statements that use statement labels; they are covered later in this
chapter. Here is an example of a labeled while
loop and a continue
statement that uses the label.
mainloop: while(token != null) { // Code omitted... continue mainloop; // Jump to top of the named loop // More code omitted... }
The break
statement,
used alone, causes the innermost enclosing loop or switch
statement to exit immediately. Its
syntax is simple:
break;
Because it causes a loop or switch
to exit, this form of the break
statement is legal only if it appears
inside one of these statements.
Youâve already seen examples of the break
statement within a switch
statement. In loops, it is typically
used to exit prematurely when, for whatever reason, there is no longer
any need to complete the loop. When a loop has complex termination
conditions, it is often easier to implement some of these conditions
with break
statements rather than
trying to express them all in a single loop expression. The following
code searches the elements of an array for a particular value. The loop
terminates in the normal way when it reaches the end of the array; it
terminates with a break
statement if
it finds what it is looking for in the array:
for(var i = 0; i < a.length; i++) { if (a[i] == target) break; }
Although it is rarely used in practice, JavaScript allows the
break
keyword to be followed by a
statement label (just the identifier, with no colon):
break labelname
;
When break
is used with a
label, it jumps to the end of, or terminates, the enclosing statement
that has the specified label. It is a syntax error to use break
in this form if there is no enclosing
statement with the specified label. With this form of the break
statement, the named statement need not
be a loop or switch
: break
can âbreak out ofâ any enclosing
statement.
The continue
statement
is similar to the break
statement.
Instead of exiting a loop, however, continue
restarts a loop at the next
iteration. The continue
statementâs
syntax is just as simple as the break
statementâs:
continue;
The continue
statement can also
be used with a label:
continue labelname
;
The continue
statement, in both
its labeled and unlabeled forms, can be used only within the body of a
loop. Using it anywhere else causes a syntax error.
The following example shows an unlabeled continue
statement being used to skip the rest
of the current iteration of a loop when an error occurs:
for(i = 0; i < data.length; i++) { if (isNaN(data[i])) continue; // Skip non-numbers. total += data[i]; }
Like the break
statement, the
continue
statement can be used in its
labeled form within nested loops, when the loop to be restarted is not
the immediately enclosing loop.
Recall that function invocations are expressions and that
all expressions have values. A return
statement within a function specifies the value of invocations of that
function. Hereâs the syntax of the return
statement:
return expression
;
A return
statement may appear
only within the body of a function. It is a syntax error for it to
appear anywhere else. When the return
statement is executed, the function that contains it returns the value
of expression
to its caller. For
example:
function square(x) { return x*x; } // Returns x squared square(2) // This invocation evaluates to 4
With no return
statement, a
function invocation simply executes each of the statements in the
function body in turn until it reaches the end of the function, and then
returns to its caller. In this case, the invocation expression evaluates
to undefined
. The return
statement can also be used without an
expression
to make the function return
undefined
before it reaches the end
of its body. For example:
function display_object(o) { // Return immediately if o is null or undefined. if (!o) return; // Rest of function goes here... }
An exception is a signal that indicates
that some sort of exceptional condition or error has occurred. To
throw an exception is to signal such an error or
exceptional condition. To catch an exception is to
handle itâto take whatever actions are necessary or appropriate to recover from the exception.
In JavaScript, exceptions are thrown whenever a runtime error occurs and
whenever the program explicitly throws one using the throw
statement. Exceptions are caught with
the try/catch/finally
statement,
which is described next.
The throw
statement has the
following syntax:
throw expression
;
expression
may evaluate to a value of
any type. You might throw a number that represents an error code or a
string that contains a human-readable error message. The Error class and
its subclasses are used when the JavaScript interpreter itself throws an
error, and you can use them as well. An Error object has a name
property that
specifies the type of error and a message
property that
holds the string passed to the constructor function (see the Error class
in the reference section). Here is an example function that throws an
Error object when invoked with an invalid argument:
function factorial(x) { // If x is invalid, throw an exception! if (x < 0) throw new Error("x must not be negative"); // Otherwise, compute a value and return normally for(var f = 1; x > 1; f *= x, x--) /* empty */ ; return f; }
When an exception is thrown, the JavaScript interpreter
immediately stops normal program execution and jumps to the nearest
exception handler. Exception handlers are written using the catch
clause of the
try/catch/finally
statement, which is
described in the next section. If the block of code in which the
exception was thrown does not have an associated catch
clause, the interpreter checks the next
highest enclosing block of code to see if it has an exception handler
associated with it. This continues until a handler is found. If an
exception is thrown in a function that does not contain a try/catch/finally
statement to handle it, the
exception propagates up to the code that invoked the function. In this
way, exceptions propagate up through the lexical structure of JavaScript
methods and up the call stack. If no exception handler is ever found,
the exception is treated as an error and is reported to the user.
The try/catch/finally
statement is JavaScriptâs exception handling mechanism. The try
clause of this statement simply defines
the block of code whose exceptions are to be handled. The try
block is followed by a catch
clause, which is a block of statements
that are invoked when an exception occurs anywhere within the try
block. The catch
clause is followed by a finally
block
containing cleanup code that is guaranteed to be executed, regardless of
what happens in the try
block. Both
the catch
and finally
blocks are optional, but a try
block must be accompanied by at least one
of these blocks. The try
, catch
, and finally
blocks all begin and end with
curly braces. These braces are a required part of the
syntax and cannot be omitted, even if a clause contains only a single
statement.
The following code illustrates the syntax and purpose of the
try/catch/finally
statement:
try { // Normally, this code runs from the top of the block // to the bottom without problems. But it can // sometimes throw an exception, either directly, with // a throw statement, or indirectly, by calling a // method that throws an exception. } catch (e) { // The statements in this block are executed if, and // only if, the try block throws an exception. These // statements can use the local variable e to refer // to the Error object or other value that was thrown. // This block may handle the exception somehow, may // ignore the exception by doing nothing, or may // rethrow the exception with throw. } finally { // This block contains statements that are always // executed, regardless of what happens in the try // block. They are executed when the try block // terminates: // 1) normally, after reaching the bottom // 2) because of a break, continue, or return // 3) with an exception handled by a catch above // 4) with an uncaught exception that is propagating }
Note that the catch
keyword is
followed by an identifier in parentheses. This identifier is like a
function parameter. When an exception is caught, the value associated
with the exception (an Error object, for example) is assigned to this
parameter. Unlike regular variables, the identifier associated with a
catch
clause has block scopeâit is
only defined within the catch
block.
Here is a realistic example of the try/catch
statement. It uses the factorial()
method
defined in the previous section and the client-side JavaScript methods
prompt()
and alert()
for input and
output:
try { // Ask the user to enter a number var n = Number(prompt("Enter an number", "")); // Compute the factorial of the number, // assuming the input is valid. var f = factorial(n); // Display the result alert(n + "! = " + f); } catch (ex) { // We end up here on invalid input. alert(ex); // Tell the user what the error is. }
This section describes the remaining three JavaScript
statementsâwith
, debugger
, and use
strict
.
When JavaScript looks up the value of a variable, it first looks
at the variables defined within the current function, then (if the
function is nested) at variables defined in enclosing functions and
finally at global variables. The with
statement
temporarily alters the way variables are looked up by specifying an
object whose properties should be treated as if they were variables. It
has the following syntax:
with (object
)statement
This statement executes statement
somewhat as if it was the body of a nested function and the properties
of object
were parameters passed to that
function.
The with
statement is forbidden
in strict mode (see âuse strictâ) and
should be considered deprecated in nonstrict mode: avoid using it
whenever possible. JavaScript code that uses with
is difficult to optimize and is likely to
run much more slowly than the equivalent code written without the
with
statement.
The debugger
statement
normally does nothing. If, however, a debugger program is available and
is running, then an implementation may (but is not required to) perform
some kind of debugging action. In practice, this statement acts like a
breakpoint: execution of JavaScript code stops and you can use the
debugger to print variablesâ values, examine the call stack, and so on.
Suppose, for example, that you are getting an exception in your function
f()
because it is being called with
an undefined argument, and you canât figure out where this call is
coming from. To help you in debugging this problem, you might alter
f()
so that it begins like
this:
function f(o) { if (o === undefined) debugger; // Debug hook // The rest of the function goes here. }
Now, when f()
is called with no
argument, execution will stop, and you can use the debugger to inspect
the call stack and find out where this incorrect call is coming
from.
The debugger
statement was
formally added to the language by ECMAScript
5, but it has been implemented by major browser vendors for
quite some time.
"use strict"
is a
directive introduced in ECMAScript 5.
Directives are not statements (but are close enough that "use strict"
is documented here). "use strict"
does not involve any JavaScript
keywords: it is simply a JavaScript string literal expression, and is
ignored by ECMAScript 3 interpreters. When placed at the beginning of a
script or of a function body, however, it has special meaning to an
ECMAScript 5 interpreter.
The purpose of a "use strict"
directive is to indicate that the
code that follows (in the script or function) is strict code. Strict code is executed
in strict mode. The strict mode of
ECMAScript 5 is a restricted
subset of the language that fixes a few important language deficiencies
and provides stronger error checking and increased security. The most
important differences between strict mode and non-strict mode are the
following:
The
with
statement is not allowed in strict mode.In strict mode, all variables must be declared: a ReferenceError is thrown if you assign a value to an identifier that is not a declared variable, parameter, or property of the global object. (In nonstrict mode, this implicitly declares a global variable by adding a new property to the global object.)
In strict mode, functions invoked as functions (rather than as methods) have a
this
value ofundefined
. (In nonstrict mode, functions invoked as functions are always passed the global object as theirthis
value.) This difference can be used to determine whether an implementation supports strict mode:var hasStrictMode = (function() { "use strict"; return this === undefined; }());
In strict mode, assignments to nonwritable properties and attempts to create new properties on nonextensible objects throw a TypeError. (In nonstrict mode, these attempts fail silently.) Similarly, in strict mode, an attempt to delete a nonconfigurable property or a nonproperty value throws a TypeError or SyntaxError. (In nonstrict mode, the attempt fails and the
delete
expression evaluates tofalse
.)In strict mode, code passed to
eval()
cannot declare variables or define functions in the callerâs scope as it can in nonstrict mode. Instead, variable and function definitions live in a new scope created for theeval()
. This scope is discarded when theeval()
returns.In strict mode, octal integer literals (beginning with a 0 that is not followed by an x) are not allowed. (In nonstrict mode, some implementations allow octal literals.)
In strict mode, the identifiers
eval
andarguments
are treated like keywords, and you are not allowed to change their value.
Get JavaScript Pocket Reference, 3rd Edition now with the O’Reilly learning platform.
O’Reilly members experience books, live events, courses curated by job role, and more from O’Reilly and nearly 200 top publishers.