This section describes the remaining three JavaScript
statements— with
, debugger
, and use
.
strict
with
In The Scope Chain, we discussed the scope
chain—a list of objects that are searched, in order, to perform
variable name resolution. The with
statement is used to temporarily
extend the scope chain. It has the following syntax:
with (object)
statement
This statement adds object
to the
front of the scope chain, executes
statement
, and then restores the scope
chain to its original state.
The with
statement is
forbidden in strict mode (see “use strict”) and
should be considered deprecated in non-strict mode: avoid using it
whenever possible. JavaScript code that uses with
is difficult to optimize and is
likely to run more slowly than the equivalent code written without
the with
statement.
The common use of the with
statement is to make it easier to work with deeply nested object
hierarchies. In client-side JavaScript, for example, you may have to
type expressions like this one to access elements of an HTML
form:
document.forms[0].address.value
If you need to write expressions like this a number of times,
you can use the with
statement to
add the form object to the scope chain:
with(document.forms[0]) {
// Access form elements directly here. For example:
name.value = "";
address.value = "";
email.value = "";
}
This reduces the amount of typing you have to do: you no
longer need to prefix each form property name with document.forms[0]
. That object is
temporarily part of the scope chain and is automatically searched
when JavaScript needs to resolve an identifier such as address
. It is just as simple, of course,
to avoid the with
statement and
write the code above like this:
var f = document.forms[0];
f.name.value = "";
f.address.value = "";
f.email.value = "";
Keep in mind that the scope chain is used only when looking up
identifiers, not when creating new ones. Consider this code:
with(o) x = 1;
If the object o
has a
property x
, then this code
assigns the value 1
to that
property. But if x
is not defined
in o
, this code is the same as
x = 1
without the with
statement. It assigns to a local or
global variable named x
, or
creates a new property of the global object. A with
statement provides a shortcut for
reading properties of o
, but not
for creating new properties of o
.
debugger
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; // Temporary line for debugging purposes
... // 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.
debugger
was formally added
to the language by ECMAScript 5, but it has been implemented by
major browser vendors for quite some time. Note that it is not
enough to have a debugger available: the debugger
statement won’t start the
debugger for you. If a debugger is already running, however, this
statement will cause a breakpoint. If you use the Firebug debugging
extension for Firefox, for example, you must have Firebug enabled
for the web page you want to debug in order for the debugger
statement to work.
“use strict”
"use strict"
is a
directive introduced in ECMAScript 5.
Directives are not statements (but are close enough that "use strict"
is documented here). There
are two important differences between the "use strict"
directive and regular
statements:
-
It does not include any language keywords: the directive
is just an expression statement that consists of a special
string literal (in single or double quotes). JavaScript
interpreters that do not implement ECMAScript 5 will simply see
an expression statement with no side effects and will do
nothing. Future versions of the ECMAScript standard are expected
to introduceuse
as a true
keyword, allowing the quotation marks to be dropped. -
It can appear only at the start of a script or at the
start of a function body, before any real statements have
appeared. It need not be the very first thing in the script or
function, however: a"use
directive may be followed or preceded by other
strict"
string literal expression statements, and JavaScript
implementations are allowed to interpret these other string
literals as implementation-defined directives. String literal
expression statements that follow the first regular statement in
a script or function are simply ordinary expression statements;
they may not be interpreted as directives and they have no
effect.
The purpose of a "use
directive is to indicate that the code that
strict"
follows (in the script or function) is strict
code. The top-level (nonfunction) code of a script is
strict code if the script has a "use
directive. A function body is strict code if it is
strict"
defined within strict code or if it has a "use strict"
directive. Code passed to the
eval()
method is strict code if
eval()
is called from strict code
or if the string of code includes a "use
directive.
strict"
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
differences between strict mode and non-strict mode are the
following (the first three are particularly important):
-
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, function, function parameter,
catch
clause parameter, or
property of the global object. (In non-strict 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 athis
value ofundefined
. (In
non-strict 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}());
Also, in strict mode, when a function is invoked with
call()
orapply()
, thethis
value is exactly the value passed
as the first argument tocall()
orapply()
. (In nonstrict mode,null
andundefined
values are replaced with the
global object and non-object values are converted to
objects.) -
In strict mode, assignments to nonwritable properties and
attempts to create new properties on nonextensible objects throw
a TypeError. (In non-strict mode, these attempts fail
silently.) -
In strict mode, code passed to
eval()
cannot declare variables or
define functions in the caller’s scope as it can in non-strict
mode. Instead, variable and function definitions live in a new
scope created for theeval()
.
This scope is discarded when theeval()
returns. -
In strict mode, the
arguments
object (Variable-Length Argument Lists: The Arguments Object) in a function holds a static copy
of the values passed to the function. In non-strict mode, the
arguments
object has
“magical” behavior in which elements of the array and named
function parameters both refer to the same value. -
In strict mode, a SyntaxError is thrown if the
delete
operator is followed by an
unqualified identifier such as a variable, function, or function
parameter. (In non-strict mode, such adelete
expression does nothing and
evaluates tofalse
.) -
In strict mode, an attempt to delete a nonconfigurable
property throws a TypeError. (In non-strict mode, the
attempt fails and thedelete
expression evaluates tofalse
.) -
In strict mode, it is a syntax error for an object literal
to define two or more properties by the same name. (In
non-strict mode, no error occurs.) -
In strict mode, it is a syntax error for a function
declaration to have two or more parameters with the same name.
(In non-strict mode, no error occurs.) -
In strict mode, octal integer literals (beginning with a 0
that is not followed by an x) are not allowed. (In non-strict
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. You cannot assign
a value to these identifiers, declare them as variables, use
them as function names, use them as function parameter names, or
use them as the identifier of acatch
block. -
In strict mode, the ability to examine the call stack is
restricted.arguments.caller
andarguments.callee
both
throw a TypeError within a strict mode function. Strict mode
functions also havecaller
andarguments
properties that
throw TypeError when read. (Some implementations define these
nonstandard properties on non-strict functions.)