This chapter is a reference for the global variables standardized by the ECMAScript specification. Web browsers have more global variables, which are listed on MDN. All global variables are (own or inherited) properties of the global object (window
in browsers; see The Global Object).
For details on the following constructors, see the sections indicated in parentheses:
Array
(The Array Constructor)
Boolean
(Wrapper Objects for Primitives)
Date
(The Date Constructor)
Function
(Evaluating Code Using new Function())
Number
(Wrapper Objects for Primitives)
Object
(Converting Any Value to an Object)
RegExp
(Creating a Regular Expression)
String
(Wrapper Objects for Primitives)
For details on these constructors, see Error Constructors:
Error
EvalError
RangeError
ReferenceError
SyntaxError
TypeError
URIError
Several global functions are not constructors. They are listed in this section.
The following functions handle several ways of URI encoding and decoding:
encodeURI(uri)
Percent-encodes special characters in uri
. Special characters are all Unicode characters except for the
following ones:
URI characters: |
|
Not encoded either: |
|
For example:
> encodeURI('http://example.com/Für Elise/') 'http://example.com/F%C3%BCr%20Elise/'
encodeURIComponent(uriComponent)
Percent-encodes all characters in uriComponent
, except for:
Not encoded: |
|
In contrast to encodeURI
, characters that are significant in URLs and filenames are encoded, too. You
can thus use this function to turn any text into a legal filename or URL path segment. For example:
> encodeURIComponent('http://example.com/Für Elise/') 'http%3A%2F%2Fexample.com%2FF%C3%BCr%20Elise%2F'
decodeURI(encodedURI)
Decodes a percent-encoded URI that has been produced by encodeURI
:
> decodeURI('http://example.com/F%C3%BCr%20Elise/') 'http://example.com/Für Elise/'
encodeURI
does not encode URI characters and decodeURI
does not decode them, even if they have been
correctly encoded:
> decodeURI('%2F') '%2F' > decodeURIComponent('%2F') '/'
decodeURIComponent(encodedURIComponent)
Decodes a percent-encoded URI component that has been produced by encodeURIComponent
. In contrast to
decodeURI
, all percent-encoded characters are decoded:
> decodeURIComponent('http%3A%2F%2Fexample.com%2FF%C3%BCr%20Elise%2F') 'http://example.com/Für Elise/'
The following are deprecated:
escape(str)
percent-encodes str
. It is deprecated because it does not handle non-ASCII characters properly. Use
encodeURIComponent()
instead.
unescape(str)
percent-decodes str
. It is deprecated because it does not handle non-ASCII characters properly. Use
decodeURIComponent()
instead.
The following methods help with categorizing and parsing numbers:
isFinite(number)
(Checking for Infinity)
isNaN(value)
(Pitfall: checking whether a value is NaN)
parseFloat(string)
(parseFloat())
parseInt(string, radix)
(Integers via parseInt())
This section examines how one can dynamically evaluate code in JavaScript.
The function call:
eval
(
str
)
evaluates the JavaScript code in str
. For example:
> var a = 12; > eval('a + 5') 17
Note that eval()
parses in statement context (see Expressions Versus Statements):
> eval('{ foo: 123 }') // code block 123 > eval('({ foo: 123 })') // object literal { foo: 123 }
For eval()
, you really should use strict mode (see Strict Mode). In sloppy mode, evaluated code can create local variables in the surrounding scope:
function
sloppyFunc
()
{
eval
(
'var foo = 123'
);
// added to the scope of sloppyFunc
console
.
log
(
foo
);
// 123
}
That can’t happen in strict mode:
function
strictFunc
()
{
'use strict'
;
eval
(
'var foo = 123'
);
console
.
log
(
foo
);
// ReferenceError: foo is not defined
}
However, even in strict mode, evaluated code still has read and write access to variables in surrounding scopes. To prevent such access, you need to call eval()
indirectly.
There are two ways to invoke eval()
:
call()
, as a method of window
, by storing it under a different name and calling it there, etc.).
As we have already seen, direct eval()
executes code in the current scope:
var
x
=
'global'
;
function
directEval
()
{
'use strict'
;
var
x
=
'local'
;
console
.
log
(
eval
(
'x'
));
// local
}
Conversely, indirect eval()
executes it in global scope:
var
x
=
'global'
;
function
indirectEval
()
{
'use strict'
;
var
x
=
'local'
;
// Don’t call eval directly
console
.
log
(
eval
.
call
(
null
,
'x'
));
// global
console
.
log
(
window
.
eval
(
'x'
));
// global
console
.
log
((
1
,
eval
)(
'x'
));
// global (1)
// Change the name of eval
var
xeval
=
eval
;
console
.
log
(
xeval
(
'x'
));
// global
// Turn eval into a method
var
obj
=
{
eval
:
eval
};
console
.
log
(
obj
.
eval
(
'x'
));
// global
}
Explanation of (1): When you refer to a variable via its name, the initial result is a so-called reference, a data structure with two main fields:
base
points to the environment, the data structure in which the variable’s value is stored.
referencedName
is the name of the variable.
During an eval()
function call, the function call operator (the parentheses) encounters a reference to eval
and can determine the name of the function to be called. Therefore, such a function call triggers a direct eval()
. You can, however, force an indirect eval()
by not giving the call operator a reference. That is achieved by retrieving the value of the reference before applying the operator. The comma operator does that for us in line (1). This operator evaluates the first operand and returns the result of evaluating the second operand. The evaluation always produces values, which means that references are resolved and function names are lost.
Indirectly evaluated code is always sloppy. That is a consequence of the code being evaluated independently of its current surroundings:
function
strictFunc
()
{
'use strict'
;
var
code
=
'(function () { return this }())'
;
var
result
=
eval
.
call
(
null
,
code
);
console
.
log
(
result
!==
undefined
);
// true, sloppy mode
}
The constructor Function()
has the signature:
new
Function
(
param1
,
...,
paramN
,
funcBody
)
It creates a function whose zero or more parameters have the names param1
, parem2
, and so on, and whose body is funcBody
; that is, the created function looks like this:
function
(
«
param1
»
,
...,
«
paramN
»
)
{
«
funcBody
»
}
Let’s use new Function()
to create a function f
that returns the sum of its parameters:
> var f = new Function('x', 'y', 'return x+y'); > f(3, 4) 7
Similar to indirect eval()
, new Function()
creates functions whose scope is global:[18]
var
x
=
'global'
;
function
strictFunc
()
{
'use strict'
;
var
x
=
'local'
;
var
f
=
new
Function
(
'return x'
);
console
.
log
(
f
());
// global
}
Such functions are also sloppy by default:
function
strictFunc
()
{
'use strict'
;
var
sl
=
new
Function
(
'return this'
);
console
.
log
(
sl
()
!==
undefined
);
// true, sloppy mode
var
st
=
new
Function
(
'"use strict"; return this'
);
console
.
log
(
st
()
===
undefined
);
// true, strict mode
}
Normally, it is better to use new Function()
than eval()
in order to evaluate code: the function parameters provide a clear interface to the evaluated code and you don’t need the slightly awkward syntax of indirect eval()
to ensure that the evaluated code can access only global variables (in addition to its own).
You should avoid eval()
and new Function()
. Dynamically evaluating code is slow and a potential security risk. It also prevents most tools (such as IDEs) that use static analysis from considering the code.
Often, there are better alternatives. For example, Brendan Eich recently tweeted an antipattern used by programmers who want to access a property whose name is stored in a variable propName
:
var
value
=
eval
(
'obj.'
+
propName
);
The idea makes sense: the dot operator only supports fixed, statically provided property keys. In this case, the property key is only known at runtime, which is why eval()
is needed in order to use that operator. Luckily, JavaScript also has the bracket operator, which does accept dynamic property keys. Therefore, the following is a better version of the preceding code:
var
value
=
obj
[
propName
];
You also shouldn’t use eval()
or new Function()
to parse JSON data. That is unsafe. Either rely on ECMAScript 5’s built-in support for JSON (see Chapter 22) or use a library.
There are a few legitimate, albeit advanced, use cases for eval()
and new Function()
: configuration data with functions (which JSON does not allow), template libraries, interpreters, command lines, and module systems.
This was a relatively high-level overview of dynamically evaluating code in JavaScript. If you want to dig deeper, you can take a look at the article “Global eval. What are the options?” by kangax.
This section provides an overview of the console API. It documents the status quo as of Chrome 32, Firebug 1.12, Firefox 25, Internet Explorer 11, Node.js 0.10.22, and Safari 7.0.
The implementations of the console API vary greatly and are constantly changing. If you want authoritative documentation, you have two options. First, you can look at standard-like overviews of the API:
Second, you can look at the documentation of various engines:
There is a bug in Internet Explorer 9. In that browser, the console
object exists only if the developer tools were open at least once. That means that you get a ReferenceError
if you refer to console
and the tools weren’t open before. As a workaround, you can check whether console
exists and create a dummy implementation if it doesn’t.
The console API includes the following logging methods:
console.clear()
console.debug(object1, object2?, ...)
console.log()
, which does the same as this method.
console.error(object1, object2?, ...)
console.exception(errorObject, object1?, ...])
[Firebug-only]
object1
etc. and show an interactive stack trace.
console.info(object1?, object2?, ...)
console.log(object1?, object2?, ...)
Log the parameters to the console. If the first parameter is a printf
-style format string, use it to print the remaining parameters. For example (Node.js REPL):
> console.log('%s', { foo: 'bar' }) [object Object] > console.log('%j', { foo: 'bar' }) {"foo":"bar"}
The only dependable cross-platform formatting directive is %s
. Node.js supports %j
to format data as JSON; browsers tend to support directives that log something interactive to the console.
console.trace()
console.warn(object1?, object2?, ...)
Support on various platforms is indicated in the following table:
Chrome | Firebug | Firefox | IE | Node.js | Safari | |
| ✓ | ✓ | ✓ | ✓ | ||
| ✓ | ✓ | ✓ | ✓ | ✓ | |
| ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
| ✓ | |||||
| ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
| ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
| ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
| ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
exception
has been typeset in italics, because it is supported only on a single platform.
The console API includes the following checking and counting methods:
console.assert(expr, obj?)
expr
is false
, log obj
to the console and throw an exception. If it is true
, do nothing.
console.count(label?)
Support on various platforms is indicated in the following table:
Chrome | Firebug | Firefox | IE | Node.js | Safari | |
| ✓ | ✓ | ✓ | ✓ | ✓ | |
| ✓ | ✓ | ✓ | ✓ |
The console API includes the following methods for formatted logging:
console.dir(object)
console.dirxml(object)
console.group(object1?, object2?, ...)
console.groupEnd()
. The block is initially expanded, but can be collapsed.
console.groupCollapsed(object1?, object2?, ...)
console.group()
, but the block is initially collapsed.
console.groupEnd()
console.group()
or console.group
Collapsed()
.
console.table(data, columns?)
Print an array as a table, one element per row. The optional parameter columns
specifies which properties/array indices are shown in the columns. If that parameter is missing, all property keys are used as table columns. Missing properties and array elements show up as undefined
in columns:
var
persons
=
[
{
firstName
:
'Jane'
,
lastName
:
'Bond'
},
{
firstName
:
'Lars'
,
lastName
:
'Croft'
,
age
:
72
}
];
// Equivalent:
console
.
table
(
persons
);
console
.
table
(
persons
,
[
'firstName'
,
'lastName'
,
'age'
]);
The resulting table is as follows:
(index) | firstName | lastName | age |
0 | “Jane” | “Bond” | undefined |
1 | “Lars” | “Croft” | 72 |
Support on various platforms is indicated in the following table:
Chrome | Firebug | Firefox | IE | Node.js | Safari | |
| ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
| ✓ | ✓ | ✓ | ✓ | ||
| ✓ | ✓ | ✓ | ✓ | ✓ | |
| ✓ | ✓ | ✓ | ✓ | ✓ | |
| ✓ | ✓ | ✓ | ✓ | ✓ | |
| ✓ | ✓ |
The console API includes the following methods for profiling and timing:
console.markTimeline(label)
[Safari-only]
console.timeStamp
.
console.profile(title?)
title
is used for the profile report.
console.profileEnd()
console.time(label)
label
.
console.timeEnd(label)
label
and print the time that has elapsed since starting it.
console.timeStamp(label?)
label
. May be logged to the console or a timeline.
Support on various platforms is indicated in the following table:
Chrome | Firebug | Firefox | IE | Node.js | Safari | |
| ✓ | |||||
| ✓ | ✓ | (devtools) | ✓ | ✓ | |
| ✓ | ✓ | (devtools) | ✓ | ✓ | |
| ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
| ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
| ✓ | ✓ |
markTimeline
has been typeset in italics, because it is supported only on a single platform. The
(devtools) designation means that the developer tools must be open in order for the method to work.[19]
The following global variables serve as namespaces for functions. For details, see the material indicated in parentheses:
JSON
Math
Object
The following global variables contain special values. For more on them, review the material indicated in parentheses:
undefined
A value expressing that something does not exist (undefined and null):
> ({}.foo) === undefined true
NaN
A value expressing that something is “not a number” (NaN):
> 1 / 'abc' NaN
Infinity
A value denoting numeric infinity ∞ (Infinity):
> 1 / 0 Infinity