Abstract
The Open JavaScript Guide is a fork of the Core JavaScript Guide. This guide is meant to give you the reference documentation even if you are off-line. The Open JavaScript Guide is available under the terms of the Creative Commons: Attribution-Sharealike license v2.5 or any later version. Code samples are available under the terms of the MIT License. More information on copyright is available in the Mozilla Developer Center copyrights page. The latest version of the Core JavaScript Guide is available in the Mozilla Developer Center.
Table of Contents
Table of Contents
JavaScript is a cross-platform, object-oriented scripting language. JavaScript is a small, lightweight language; it is not useful as a standalone language, but is designed for easy embedding in other products and applications, such as web browsers. Inside a host environment, JavaScript can be connected to the objects of its environment to provide programmatic control over them.
Core JavaScript contains a core set of objects, such as
Array
, Date
,
and Math
, and a core set of language
elements such as operators, control structures, and statements.
Core JavaScript can be extended for a variety of purposes by
supplementing it with additional objects; for example:
Client-side JavaScript extends the core language by supplying objects to control a browser (Navigator or another web browser) and its Document Object Model (DOM). For example, client-side extensions allow an application to place elements on an HTML form and respond to user events such as mouse clicks, form input, and page navigation.
Server-side JavaScript extends the core language by supplying objects relevant to running JavaScript on a server. For example, server-side extensions allow an application to communicate with a relational database, provide continuity of information from one invocation to another of the application, or perform file manipulations on a server.
JavaScript and Java are similar in some ways but fundamentally different in others. The JavaScript language resembles Java but does not have Java's static typing and strong type checking. JavaScript supports most Java expression syntax and basic control-flow constructs.
In contrast to Java's compile-time system of classes built by
declarations, JavaScript supports a runtime system based on a small
number of data types representing numeric, Boolean
, and string values. JavaScript has a
prototype-based object model instead of the more common class-based
object model. The prototype-based model provides dynamic
inheritance; that is, what is inherited can vary for individual
objects. JavaScript also supports functions without any special
declarative requirements. Functions can be properties of objects,
executing as loosely typed methods.
JavaScript is a very free-form language compared to Java. You do not have to declare all variables, classes, and methods. You do not have to be concerned with whether methods are public, private, or protected, and you do not have to implement interfaces. Variables, parameters, and function return types are not explicitly typed.
Java is a class-based programming language designed for fast execution and type safety. Type safety means, for instance, that you can't cast a Java integer into an object reference or access private memory by corrupting Java bytecodes. Java's class-based model means that programs consist exclusively of classes and their methods. Java's class inheritance and strong typing generally require tightly coupled object hierarchies. These requirements make Java programming more complex than JavaScript authoring.
In contrast, JavaScript descends in spirit from a line of smaller, dynamically typed languages such as HyperTalk and dBASE. These scripting languages offer programming tools to a much wider audience because of their easier syntax, specialized built-in functionality, and minimal requirements for object creation.
JavaScript | Java |
---|---|
Object-oriented. No distinction between types of objects. Inheritance is through the prototype mechanism, and properties and methods can be added to any object dynamically. | Class-based. Objects are divided into classes and instances with all inheritance through the class hierarchy. Classes and instances cannot have properties or methods added dynamically. |
Variable data types not declared (dynamic typing). | Variable data types must be declared (static typing). |
Cannot automatically write to hard disk. | Cannot automatically write to hard disk. |
Table 1.1: JavaScript compared to Java
Netscape invented JavaScript, and JavaScript was first used in Netscape browsers. However, Netscape is working with Ecma International - the European association for standardizing information and communication systems (formerly known as Ecma - the European Computer Manufacturers Association) to deliver a standardized, international programming language based on core JavaScript. This standardized version of JavaScript, called ECMAScript, behaves the same way in all applications that support the standard. Companies can use the open standard language to develop their implementation of JavaScript. The ECMAScript standard is documented in the ECMA-262 specification.
The ECMA-262 standard is also approved by the ISO (International Organization for Standardization) as ISO-16262. You can find a PDF version of ECMA-262 at the Mozilla website. You can also find the specification on the Ecma International website. The ECMAScript specification does not describe the Document Object Model (DOM), which is standardized by the World Wide Web Consortium (W3C). The DOM defines the way in which HTML document objects are exposed to your script.
Netscape worked closely with Ecma International to produce the ECMAScript Specification (ECMA-262). The following table describes the relationship between JavaScript versions and ECMAScript editions.
JavaScript version | Relationship to ECMAScript edition |
---|---|
JavaScript 1.1 | ECMA-262, Edition 1 is based on JavaScript 1.1. |
JavaScript 1.2 |
ECMA-262 was not complete when JavaScript 1.2 was
released. JavaScript 1.2 is not fully compatible with
ECMA-262, Edition 1, for the following reasons:
|
JavaScript 1.3 |
JavaScript 1.3 is fully compatible with ECMA-262, Edition 1. JavaScript 1.3 resolved the inconsistencies that JavaScript 1.2 had with ECMA-262, while keeping all the additional features of JavaScript 1.2 except == and !=, which were changed to conform with ECMA-262. |
JavaScript 1.4 |
JavaScript 1.4 is fully compatible with ECMA-262, Edition 1. The third version of the ECMAScript specification was not finalized when JavaScript 1.4 was released. |
JavaScript 1.5 | JavaScript 1.5 is fully compatible with ECMA-262, Edition 3. |
Table 1.2: JavaScript versions and ECMAScript editions
Note: ECMA-262, Edition 2 consisted of minor editorial changes and bug fixes to the Edition 1 specification. The TC39 working group of Ecma International is currently working on ECMAScript Edition 4, which will correspond to a future release of JavaScript, JavaScript 2.0.
JavaScript will always include features that are not part of the ECMAScript Specification; JavaScript is compatible with ECMAScript, while providing additional features.
The ECMAScript specification is a set of requirements for implementing ECMAScript; it is useful if you want to determine whether a JavaScript feature is supported in other ECMAScript implementations. If you plan to write JavaScript code that uses only features supported by ECMAScript, then you may need to review the ECMAScript specification.
The ECMAScript document is not intended to help script programmers; use the JavaScript documentation for information on writing scripts.
JavaScript recognizes the following types of values:
Number, such as 42 or 3.14159
Boolean values, either true
or false
String, such as "Howdy!"
null
, a special keyword denoting
a null value; null is also a primitive value. Because
JavaScript is case-sensitive, null
is not the same as Null, NULL, or any other variant
undefined, a top-level property whose value
is undefined; undefined
is also a
primitive value.
This relatively small set of types of values, or data types, enables you to perform useful functions with your applications. There is no explicit distinction between integer and real-valued numbers. Nor is there an explicit date data type in JavaScript. However, you can use the Date object and its methods to handle dates. Object and Function are the other fundamental elements in the language. You can think of objects as named containers for values, and functions as procedures that your application can perform.
JavaScript is a dynamically typed language. That means you do not have to specify the data type of a variable when you declare it, and data types are converted automatically as needed during script execution. So, for example, you could define a variable as follows:
var answer = 42
And later, you could assign the same variable a string value, for example:
answer = "Thanks for all the fish..."
Because JavaScript is dynamically typed, this assignment does not cause an error message.
In expressions involving numeric and string values with the + operator, JavaScript converts numeric values to strings. For example, consider the following statements:
x = "The answer is " + 42 // returns "The answer is 42" y = 42 + " is the answer" // returns "42 is the answer"
In statements involving other operators, JavaScript does not convert numeric values to strings. For example:
"37" - 7 // returns 30 "37" + 7 // returns "377"
You use variables as symbolic names for values in your application. The names of variables, called identifiers, conform to certain rules.
A JavaScript identifier must start with a letter, underscore (_), or dollar sign ($); subsequent characters can also be digits (0-9). Because JavaScript is case sensitive, letters include the characters "A" through "Z" (uppercase) and the characters "a" through "z" (lowercase).
Starting with JavaScript 1.5, you can use ISO 8859-1 or Unicode letters in identifiers. You can also use the \uXXXX Unicode escape sequences listed on the Unicode escape sequences page as characters in identifiers.
Some examples of legal names are Number_hits
, temp99
, and
_name
.
You can declare a variable in two ways:
With the keyword var. For example, var x = 42
. This syntax can be used to
declare both Variable Scope variables.
By simply assigning it a value. For example,
x = 42
. This always declares a
Global variables are in fact properties of the global object. In web pages the global object is window, so you can set and access global variables using the window.variable syntax.
Consequently, you can access global variables declared
in one window or frame from another window or frame by
specifying the window or frame name. For example, if a
variable called phoneNumber
is
declared in a frameset
document,
you can refer to this variable from a child frame as
parent.phoneNumber
.
A variable declared using the var statement with no initial
value specified has the value undefined
.
An attempt to access an undeclared variable will result in a
ReferenceError
exception being
thrown:
var a; print("The value of a is " + a); // prints "The value of a is undefined" print("The value of b is " + b); // throws ReferenceError exception
You can use undefined
to determine
whether a variable has a value. In the following code, the
variable input is not assigned a value, and the if...else statement evaluates to true
.
var input; if (input === undefined){ doThis(); } else { doThat(); }
The undefined
value behaves as
false
when used in a boolean context.
For example, the following code executes the function
myFunction
because the myArray
element is not defined:
myArray=new Array() if (!myArray[0]) myFunction();
When you evaluate a null variable, the null value behaves as 0
in numeric contexts and as false
in
boolean contexts. For example:
var n = null; n * 32; //returns 0
When you declare a variable outside of any function, it is called a global variable, because it is available from any other code in the current document. When you declare a variable within a function, it is called a local variable, because it is available only within that function.
Global variables are in fact properties of the global object. In web pages the global object is window, so you can set and access global variables using the window.variable syntax.
Consequently, you can access global variables declared in one
window or frame from another window or frame by specifying the
window or frame name. For example, if a variable called
phoneNumber
is declared in a
frameset
document, you can refer to
this variable from a child frame as parent.phoneNumber
.
You can create a read-only, named constant with the const keyword. The syntax of a constant identifier is the same as for a variable identifier: it must start with a letter or underscore and can contain alphabetic, numeric, or underscore characters.
const prefix = '212';
A constant cannot change value through assignment or be re-declared while the script is running.
The scope rules for constants are the same as those for variables, except that the const keyword is always required, even for global constants. If the keyword is omitted, the identifier is assumed to represent a variable.
You cannot declare a constant with the same name as a function or variable in the same scope. For example:
//this will cause an error function f() {}; const f = 5; //this will cause an error also function f() { const g = 5; var g; //statements }
You use literals to represent values in JavaScript. These are fixed values, not variables, that you literally provide in your script. This section describes the following types of literals:
An array literal is a list of zero or more expressions, each of which represents an array element, enclosed in square brackets ([]). When you create an array using an array literal, it is initialized with the specified values as its elements, and its length is set to the number of arguments specified.
The following example creates the coffees array with three elements and a length of three:
coffees = ["French Roast", "Colombian", "Kona"]
Note An array literal is a type of object initializer. See Using Object Initializers.
If an array is created using a literal in a top-level script, JavaScript interprets the array each time it evaluates the expression containing the array literal. In addition, a literal used in a function is created each time the function is called.
Array literals are also Array
objects. See Array Object for details on Array
objects.
You do not have to specify all elements in an array literal. If you put two commas in a row, the array is created with spaces for the unspecified elements. The following example creates the fish array:
fish = ["Lion", , "Angel"]
This array has two elements with values and one empty
element (fish[0]
is "Lion
", fish[1]
is
undefined
, and fish[2]
is "Angel").
If you include a trailing comma at the end of the list of
elements, the comma is ignored. In the following example, the
length of the array is three. There is no myList[3]
. All other commas in the list indicate
a new element.
myList = ['home', , 'school', ];
In the following example, the length of the array is four,
and myList[0]
and myList[2]
are missing.
myList = [ , 'home', , 'school'];
In the following example, the length of the array is four,
and myList[1]
and myList[3]
are missing. Only the last comma is
ignored. This trailing comma is optional.
myList = ['home', , 'school', , ];
The Boolean
type has two literal
values: true
and false
.
Do not confuse the primitive Boolean
values true
and false
with the true
and
false
values of the Boolean
object. The Boolean
object is a wrapper around the primitive
Boolean
data type. See Boolean Object
for more information.
Integers can be expressed in decimal (base 10), hexadecimal (base 16), and octal (base 8). A decimal integer literal consists of a sequence of digits without a leading 0 (zero). A leading 0 (zero) on an integer literal indicates it is in octal; a leading 0x (or 0X) indicates hexadecimal. Hexadecimal integers can include digits (0-9) and the letters a-f and A-F. Octal integers can include only the digits 0-7.
Octal integer literals are deprecated and have been removed from the ECMA-262, Edition 3 standard. JavaScript 1.5 still supports them for backward compatibility.
Some examples of integer literals are:
0, 117 and -345 (decimal, base 10) 015, 0001 and -077 (octal, base 8) 0x1123, 0x00111 and -0xF1A7 (hexadecimal, "hex" or base 16)
A floating-point literal can have the following parts:
A decimal integer which can be signed (preceded by "+" or "-"),
A decimal point ("."),
A fraction (another decimal number),
An exponent.
The exponent part is an "e" or "E" followed by an integer, which can be signed (preceded by "+" or "-"). A floating-point literal must have at least one digit and either a decimal point or "e" (or "E").
Some examples of floating-point literals are 3.1415, -3.1E12, .1e12, and 2E-12.
More succinctly, the syntax is: [digits][.digits][(E|e)[(+|-)]digits]
For example:
3.14 2345.789 .3333333333333333333
An object literal is a list of zero or more pairs of property names and associated values of an object, enclosed in curly braces ({}). You should not use an object literal at the beginning of a statement. This will lead to an error or not behave as you expect, because the { will be interpreted as the beginning of a block.
The following is an example of an object literal. The first
element of the car
object defines a
property, myCar
; the second element,
the getCar
property, invokes a function
(CarTypes("Honda")
); the third element,
the special property, uses an existing variable (Sales).
var Sales = "Toyota"; function CarTypes(name) { if(name == "Honda") return name; else return "Sorry, we don't sell " + name + "."; } car = {myCar: "Saturn", getCar: CarTypes("Honda"), special: Sales} document.write(car.myCar); // Saturn document.write(car.getCar); // Honda document.write(car.special); // Toyota
Additionally, you can use a numeric or string literal for the name of a property or nest an object inside another. The following example uses these options.
car = {manyCars: {a: "Saab", b: "Jeep"}, 7: "Mazda"} document.write(car.manyCars.b); // Jeep document.write(car[7]); // Mazda
Please note:
foo = {a: "alpha", 2: "two"} document.write (foo.a) // alpha document.write (foo[2]) // two //document.write (foo.2) // Error: missing ) after argument list //document.write (foo[a]) // Error: a is not defined document.write (foo["a"]) // alpha document.write (foo["2"]) // two
A string literal is zero or more characters enclosed in double (") or single (') quotation marks. A string must be delimited by quotation marks of the same type; that is, either both single quotation marks or both double quotation marks. The following are examples of string literals:
"blah"
'blah'
"1234"
"one line \n another line"
"John's cat"
You can call any of the methods of the String
object on a string literal value -
JavaScript automatically converts the string literal to a
temporary String
object, calls the
method, then discards the temporary String
object. You can also use the String.length
property with a string literal:
"John's cat".length
You should use string literals unless you specifically need to
use a String
object. See String
Object for details on String
objects.
In addition to ordinary characters, you can also include special characters in strings, as shown in the following example.
"one line \n another line"
The following table lists the special characters that you can use in JavaScript strings.
Character | Meaning |
---|---|
\b | Backspace |
\f | Form feed |
\n | New line |
\r | Carriage return |
\t | Tab |
\v | Vertical tab |
\' | Apostrophe or single quote |
\" | Double quote |
\\ | Backslash character (\). |
\XXX | The character with the Latin-1 encoding specified by up to three octal digits XXX between 0 and 377. For example, \251 is the octal sequence for the copyright symbol. |
\xXX | The character with the Latin-1 encoding specified by the two hexadecimal digits XX between 00 and FF. For example, \xA9 is the hexadecimal sequence for the copyright symbol. |
\uXXXX | The Unicode character specified by the four hexadecimal digits XXXX. For example, \u00A9 is the Unicode sequence for the copyright symbol. See . |
Table 2.1: JavaScript special characters
For characters not listed in Table 2.1, a preceding backslash is ignored, but this usage is deprecated and should be avoided.
You can insert a quotation mark inside a string by preceding it with a backslash. This is known as escaping the quotation mark. For example:
var quote = "He read \"The Cremation of Sam McGee\" by R.W. Service." document.write(quote)
The result of this would be:
He read "The Cremation of Sam McGee" by R.W. Service.
To include a literal backslash inside a string, you must escape the backslash character. For example, to assign the file path c:\temp to a string, use the following:
var home = "c:\\temp"
Unicode is a character-coding standard for the interchange and display of principal written languages. Unicode allows for the exchange, processing, and display of multilingual texts, as well as the use of common technical and mathematical symbols. It hopes to resolve internationalization problems of multilingual computing, such as different national character standards. Not all modern or archaic scripts, however, are currently supported.
The Unicode character set can be used for all known encoding. Unicode is modeled after the ASCII (American Standard Code for Information Interchange) character set. It uses a numerical value and name for each character. The character encoding specifies the identity of the character and its numeric value (code position), as well as the representation of this value in bits. The 16-bit numeric value (code value) is defined by a hexadecimal number and a prefix U, for example, U+0041 represents A. The unique name for this value is LATIN CAPITAL LETTER A.
Unicode is not supported in versions of JavaScript prior to 1.3.
Unicode is fully compatible with the International Standard ISO/IEC 10646-1; 1993, which is a subset of ISO 10646.
Several encoding standards (including UTF-8, UTF-16 and ISO UCS-2) are used to physically represent Unicode as actual bits.
The UTF-8 encoding of Unicode is compatible with ASCII characters and is supported by many programs. The first 128 Unicode characters correspond to the ASCII characters and have the same byte value. The Unicode characters U+0020 through U+007E are equivalent to the ASCII characters 0x20 through 0x7E. Unlike ASCII, which supports the Latin alphabet and uses a 7-bit character set, UTF-8 uses between one and four octets for each character. ("Octet" meaning a byte, or 8 bits.) This allows for several million characters. An alternative encoding standard, UTF-16, uses two octets to represent Unicode characters. An escape sequence allows UTF-16 to represent the whole Unicode range by using four octets.
JavaScript support for UTF-8/Unicode means you can use non-Latin, international, and localized characters, plus special technical symbols in JavaScript programs. Since the UTF-8 encoding of Unicode is compatible with ASCII, programs can use ASCII characters. You can use non-ASCII Unicode characters in the comments, string literals, identifiers, and regular expressions of JavaScript.
You can use the Unicode escape sequence in string literals, regular expressions, and identifiers. The escape sequence consists of six ASCII characters: \u and a four-digit hexadecimal number. For example, \u00A9 represents the copyright symbol. Every Unicode escape sequence in JavaScript is interpreted as one character.
The following code returns the copyright symbol and the string "Netscape Communications".
x="\u00A9 Netscape Communications"
The following table lists frequently used special characters and their Unicode value.
Category | Unicode value | Name | Format name |
---|---|---|---|
White space values | \u0009 | Tab | <TAB> |
\u000B | Vertical Tab | <VT> | |
\u000C | Form Feed | <FF> | |
\u0020 | Space | <SP> | |
Line terminator values | \u000A | Line Feed | <LF> |
\u000D | Carriage Return | <CR> | |
Additional Unicode escape sequence values | \u0008 | Backspace | <BS> |
\u0009 | Horizontal Tab | <HT> | |
\u0022 | Double Quote | " | |
\u0027 | Single Quote | ' | |
\u005C | Backslash | \ |
Table 2.2: Unicode values for special characters
You can use Unicode to display the characters in different languages or technical symbols. For characters to be displayed properly, a client such as Mozilla Firefox needs to support Unicode. Moreover, an appropriate Unicode font must be available to the client, and the client platform must support Unicode. Often, Unicode fonts do not display all the Unicode characters. Some platforms, such as Windows 95, provide only a partial support for Unicode.
For more information on Unicode, see the Unicode Home Page and The Unicode Standard, Version 2.0, published by Addison-Wesley, 1996.
Table of Contents
An expression is any valid set of literals, variables, operators, and expressions that evaluates to a single value; the value can be a number, a string, or a logical value.
Conceptually, there are two types of expressions: those that
assign a value to a variable, and those that simply have a value.
For example, the expression x = 7
is an
expression that assigns x the value seven. This expression itself
evaluates to seven. Such expressions use assignment operators. On the other hand,
the expression 3 + 4
simply evaluates to
seven; it does not perform an assignment. The operators used in
such expressions are referred to simply as operators.
JavaScript has the following types of expressions:
Arithmetic: evaluates to a number, for example 3.14159. (Generally uses Arithmetic Operators.)
String: evaluates to a character string, for example, "Fred" or "234". (Generally uses String Operators.)
Logical: evaluates to true
or
false
. (Often involves Logical Operators.)
Object: evaluates to an object. (See Special Operators for various ones that evaluate to objects.)
JavaScript has the following types of operators.
This section describes the operators and contains information about operator precedence.
JavaScript has both binary and unary operators. A binary operator requires two operands, one before the operator and one after the operator:
operand1 operator operand2
For example, 3+4
or x*y
.
A unary operator requires a single operand, either before or after the operator:
operator operand
or
operand operator
For example, x++
or ++x
.
In addition, JavaScript has one ternary operator, the conditional operator. A ternary operator requires three operands.
Operator type | Individual operators |
---|---|
member | . [] |
call / create instance | () new |
negation/increment | ! ~ - + ++ -- typeof void delete |
multiply/divide | * / % |
addition/subtraction | + - |
bitwise shift | << >> >>> |
relational | < <= > >= in instanceof |
equality | == != === !== |
bitwise-and | & |
bitwise-xor | ^ |
bitwise-or | | |
logical-and | && |
logical-or | || |
conditional | ?: |
assignment | = += -= *= /= %= <<= >>= >>>= &= ^= |= |
comma | , |
Table 3.1: Operator precedence
An assignment operator assigns a value to its left operand based on the value of its right operand. The basic assignment operator is equal (=), which assigns the value of its right operand to its left operand. That is, x = y assigns the value of y to x.
The other assignment operators are shorthand for standard operations, as shown in the following table.
Shorthand operator | Meaning |
---|---|
x += y |
x = x + y |
x -= y |
x = x - y |
x *= y |
x = x * y |
x /= y |
x = x / y |
x %= y |
x = x % y |
x <<= y |
x = x << y |
x >>= y |
x = x >> y |
x >>>= y |
x = x >>> y |
x &= y |
x = x & y |
x ^= y |
x = x ^ y |
x |= y |
x = x | y |
Table 3.2: Assignment operators
A comparison operator compares its operands and returns a
logical value based on whether the comparison is true
. The operands can be numerical, string, logical,
or object values. Strings are compared based on standard
lexicographical ordering, using Unicode values. If the two operands
are not of the same type, JavaScript attempts to convert the
operands to an appropriate type for the comparison, except for the
=== and !== operators. This generally results in a numerical
comparison being performed. The following table describes the
comparison operators.
Operator | Description | Examples returning true |
---|---|---|
Equal (==) | Returns true if the operands
are equal. |
|
Not equal (!=) | Returns true if the operands
are not equal. |
|
Strict equal (===) | Returns true if the operands
are equal and of the same type. |
3 === var1 |
Strict not equal (!==) | Returns true if the operands
are not equal and/or not of the same type. |
|
Greater than (>) | Returns true if the left
operand is greater than the right operand. |
|
Greater than or equal (>=) | Returns true if the left
operand is greater than or equal to the right operand. |
|
Less than (<) | Returns true if the left
operand is less than the right operand. |
|
Less than or equal (<=) | Returns true if the left
operand is less than or equal to the right operand. |
|
Table 3.3: Comparison operators
These examples assume that var1
has
been assigned the value 3 and var2
has
been assigned the value 4.
Arithmetic operators take numerical values (either literals or variables) as their operands and return a single numerical value. The standard arithmetic operators are addition (+), subtraction (-), multiplication (*), and division (/). These operators work as they do in most other programming languages, except the / operator returns a floating-point division in JavaScript, not a truncated division as it does in languages such as C or Java. For example:
1/2 //returns 0.5 in JavaScript 1/2 //returns 0 in Java
In addition, JavaScript provides the arithmetic operators listed in the following table.
Operator | Description | Example |
---|---|---|
% (Modulus) | Binary operator. Returns the integer remainder of dividing the two operands. | 12 % 5 returns 2. |
++ (Increment) | Unary operator. Adds one to its operand. If used as a
prefix operator (++x ), returns
the value of its operand after adding one; if used as a
postfix operator (x++ ), returns
the value of its operand before adding one. |
If x is 3, then ++x sets x to
4 and returns 4, whereas x++ sets x to 4 and returns
3. |
-- (Decrement) | Unary operator. Subtracts one from its operand. The return value is analogous to that for the increment operator. | If x is 3, then --x sets x to
2 and returns 2, whereas x-- sets
x to 2 and returns 3. |
- (Unary negation) | Unary operator. Returns the negation of its operand. | If x is 3, then -x returns
-3. |
Table 3.4: Arithmetic Operators
Bitwise operators treat their operands as a set of 32 bits (zeros and ones), rather than as decimal, hexadecimal, or octal numbers. For example, the decimal number nine has a binary representation of 1001. Bitwise operators perform their operations on such binary representations, but they return standard JavaScript numerical values.
The following table summarizes JavaScript's bitwise operators.
Operator | Usage | Description |
---|---|---|
Bitwise AND | a & b |
Returns a one in each bit position for which the corresponding bits of both operands are ones. |
Bitwise OR | a | b |
Returns a one in each bit position for which the corresponding bits of either or both operands are ones. |
Bitwise XOR | a ^ b |
Returns a one in each bit position for which the corresponding bits of either but not both operands are ones. |
Bitwise NOT | ~ a |
Inverts the bits of its operand. |
Left shift | a << b |
Shifts a in binary representation b bits to the left, shifting in zeros from the right. |
Sign-propagating right shift | a >> b |
Shifts a in binary representation b bits to the right, discarding bits shifted off. |
Zero-fill right shift | a >>> b |
Shifts a in binary representation b bits to the right, discarding bits shifted off, and shifting in zeros from the left. |
Table 3.5: Bitwise operators
Conceptually, the bitwise logical operators work as follows:
The operands are converted to thirty-two-bit integers and expressed by a series of bits (zeros and ones).
Each bit in the first operand is paired with the corresponding bit in the second operand: first bit to first bit, second bit to second bit, and so on.
The operator is applied to each pair of bits, and the result is constructed bitwise.
For example, the binary representation of nine is 1001, and the binary representation of fifteen is 1111. So, when the bitwise operators are applied to these values, the results are as follows:
15 & 9
yields 9 (1111
& 1001 = 1001)
15 | 9
yields 15 (1111 | 1001
= 1111)
15 ^ 9
yields 6 (1111 ^ 1001 =
0110)
The bitwise shift operators take two operands: the first is a quantity to be shifted, and the second specifies the number of bit positions by which the first operand is to be shifted. The direction of the shift operation is controlled by the operator used.
Shift operators convert their operands to thirty-two-bit integers and return a result of the same type as the left operand.
The shift operators are listed in the following table.
Operator | Description | Example |
---|---|---|
<< (Left shift) | This operator shifts the first operand the specified number of bits to the left. Excess bits shifted off to the left are discarded. Zero bits are shifted in from the right. | 9<<2 yields 36,
because 1001 shifted 2 bits to the left becomes 100100,
which is 36. |
>> (Sign-propagating right shift) | This operator shifts the first operand the specified number of bits to the right. Excess bits shifted off to the right are discarded. Copies of the leftmost bit are shifted in from the left. | 9>>2 yields 2,
because 1001 shifted 2 bits to the right becomes 10,
which is 2. Likewise, -9>>2 yields -3, because the sign is
preserved. |
>>> (Zero-fill right shift) | This operator shifts the first operand the specified number of bits to the right. Excess bits shifted off to the right are discarded. Zero bits are shifted in from the left. | 19>>>2 yields 4,
because 10011 shifted 2 bits to the right becomes 100,
which is 4. For non-negative numbers, zero-fill right
shift and sign-propagating right shift yield the same
result. |
Table 3.6: Bitwise shift operators
Logical operators are typically used with Boolean
(logical) values; when they are, they return
a Boolean
value. However, the &&
and || operators actually return the value of one of the specified
operands, so if these operators are used with non-Boolean values,
they may return a non-Boolean value. The logical operators are
described in the following table.
Operator | Usage | Description |
---|---|---|
&& |
expr1 && expr2 |
(Logical AND) Returns expr1
if it can be converted to false ;
otherwise, returns expr2 . Thus,
when used with Boolean values,
&& returns true if both
operands are true ; otherwise,
returns false . |
|| |
expr1 || expr2 |
(Logical OR) Returns expr1 if
it can be converted to true ;
otherwise, returns expr2 . Thus,
when used with Boolean values,
|| returns true if either operand is true ; if both are false , returns false . |
! | !expr |
(Logical NOT) returns false
if its single operand can be converted to true ; otherwise, returns true . |
Table 3.7: Logical operators
Examples of expressions that can be converted to false
are those that evaluate to null
, 0
, the empty string
(""), or undefined
.
The following code shows examples of the && (logical AND) operator.
a1=true && true // t && t returns true a2=true && false // t && f returns false a3=false && true // f && t returns false a4=false && (3 == 4) // f && f returns false a5="Cat" && "Dog" // t && t returns Dog a6=false && "Cat" // f && t returns false a7="Cat" && false // t && f returns false
The following code shows examples of the || (logical OR) operator.
o1=true || true // t || t returns true o2=false || true // f || t returns true o3=true || false // t || f returns true o4=false || (3 == 4) // f || f returns false o5="Cat" || "Dog" // t || t returns Cat o6=false || "Cat" // f || t returns Cat o7="Cat" || false // t || f returns Cat
The following code shows examples of the ! (logical NOT) operator.
n1=!true // !t returns false n2=!false // !f returns true n3=!"Cat" // !t returns false
As logical expressions are evaluated left to right, they are tested for possible "short-circuit" evaluation using the following rules:
false
&& anything is short-circuit
evaluated to false
.
true
|| anything is short-circuit
evaluated to true
.
The rules of logic guarantee that these evaluations are always correct. Note that the anything part of the above expressions is not evaluated, so any side effects of doing so do not take effect.
In addition to the comparison operators, which can be used on
string values, the concatenation operator (+
) concatenates two string values together,
returning another string that is the union of the two operand
strings. For example, "my " + "string"
returns the string "my string".
The shorthand assignment operator += can also be used to
concatenate strings. For example, if the variable mystring has
the value "alpha", then the expression mystring += "bet"
evaluates to "alphabet" and
assigns this value to mystring
.
JavaScript provides the following special operators:
The conditional operator is the only JavaScript operator that takes three operands. The operator can have one of two values based on a condition. The syntax is:
condition ? val1 : val2
If condition is true
, the operator
has the value of val1
. Otherwise it has
the value of val2
. You can use the
conditional operator anywhere you would use a standard
operator.
For example,
status = (age >= 18) ? "adult" : "minor"
This statement assigns the value "adult"
to the variable status if age
is eighteen or more. Otherwise, it assigns the
value "minor"
to status
.
The comma operator (,
) simply
evaluates both of its operands and returns the value of the
second operand. This operator is primarily used inside a for
loop, to allow multiple variables to be updated each time through
the loop.
For example, if a is a 2-dimensional array with 10 elements on a side, the following code uses the comma operator to increment two variables at once. The code prints the values of the diagonal elements in the array:
for (var i=0, j=9; i <= 9; i++, j--) document.writeln("a["+i+"]["+j+"]= " + a[i][j])
The delete
operator deletes an
object, an object's property, or an element at a specified index
in an array. The syntax is:
delete objectName delete objectName.property delete objectName[index] delete property // legal only within a with statement
where objectName
is the name of an
object, property is an existing property, and index is an integer
representing the location of an element in an array.
The fourth form is legal only within a with statement, to delete a property from an object.
You can use the delete operator to delete variables declared implicitly but not those declared with the var statement.
If the delete operator succeeds, it sets the property or
element to undefined
. The delete
operator returns true
if the operation
is possible; it returns false
if the
operation is not possible.
x=42 var y= 43 myobj=new Number() myobj.h=4 // create property h delete x // returns true (can delete if declared implicitly) delete y // returns false (cannot delete if declared with var) delete Math.PI // returns false (cannot delete predefined properties) delete myobj.h // returns true (can delete user-defined properties) delete myobj // returns true (can delete if declared implicitly)
Deleting array
elements When you delete an array element, the
array length is not affected. For example, if you delete
a[3]
, a[4]
is
still a[4]
and a[3]
is undefined
.
When the delete
operator removes an
array element, that element is no longer in the array. In the
following example, trees[3]
is removed
with delete
.
trees=new Array("redwood","bay","cedar","oak","maple") delete trees[3] if (3 in trees) { // this does not get executed }
If you want an array element to exist but have an undefined
value, use the undefined
keyword instead of the delete
operator. In the following example,
trees[3]
is assigned the value
undefined
, but the array element still
exists:
trees=new Array("redwood","bay","cedar","oak","maple") trees[3]=undefined if (3 in trees) { // this gets executed }
The in
operator returns true
if the specified property is in the specified
object. The syntax is:
propNameOrNumber in objectName
where propNameOrNumber
is a string
or numeric expression representing a property name or array
index, and objectName
is the name of an
object.
The following examples show some uses of the in operator.
// Arrays trees=new Array("redwood","bay","cedar","oak","maple") 0 in trees // returns true 3 in trees // returns true 6 in trees // returns false "bay" in trees // returns false (you must specify the index number, // not the value at that index) "length" in trees // returns true (length is an Array property) // Predefined objects "PI" in Math // returns true myString=new String("coral") "length" in myString // returns true // Custom objects mycar = {make:"Honda",model:"Accord",year:1998} "make" in mycar // returns true "model" in mycar // returns true
The instanceof
operator returns
true
if the specified object is of the
specified object type. The syntax is:
objectName instanceof objectType
where objectName
is the name of the
object to compare to objectType
, and
objectType
is an object type, such as
Date
or Array
.
Use instanceof
when you need to
confirm the type of an object at runtime. For example, when
catching exceptions, you can branch to different
exception-handling code depending on the type of exception
thrown.
For example, the following code uses instanceof to determine
whether theDay
is a Date
object. Because theDay
is a Date
object,
the statements in the if statement execute.
theDay=new Date(1995, 12, 17) if (theDay instanceof Date) { // statements to execute }
You can use the new
operator to
create an instance of a user-defined object type or of one of the
predefined object types Array
,
Boolean
, Date
, Function
,
Image
, Number
,Object
,
Option
, RegExp
, or String
. Use
new
as follows:
objectName = new objectType ( param1 [,param2] ...[,paramN] )
You can also create objects using object initializers, as described in Using Object Initializers.
See the new Operator page in the Core JavaScript Reference for more information.
Use the this
keyword to refer to the
current object. In general, this
refers
to the calling object in a method. Use this
as follows:
this[.propertyName]
Example 1.
Suppose a function called validate validates an object's value property, given the object and the high and low values:
function validate(obj, lowval, hival) { if ((obj.value < lowval) || (obj.value > hival)) alert("Invalid Value!") }
You could call validate in each form element's onchange
event handler, using this to pass it the
form element, as in the following example:
<B>Enter a number between 18 and 99:</B> <input type="text" name= "age" size="3" onchange="validate(this, 18, 99)">
Example 2.
When combined with the form property, this can refer to the
current object's parent form. In the following example, the form
myForm
contains a Text
object and a button. When the user clicks the
button, the value of the Text
object is
set to the form's name. The button's onclick
event handler uses this.form
to refer to the parent form, myForm
.
<form name="myForm"> Form name:<input type="text" name="text1" value="Beluga"> <p> <input name="button1" type="button" value="Show Form Name" onclick="this.form.text1.value=this.form.name"> </form>
The typeof
operator is used in
either of the following ways:
1. typeof operand 2. typeof (operand)
The typeof
operator returns a string
indicating the type of the unevaluated operand. operand is the
string, variable, keyword, or object for which the type is to be
returned. The parentheses are optional.
Suppose you define the following variables:
var myFun = new Function("5+2") var shape="round" var size=1 var today=new Date()
The typeof operator returns the following results for these variables:
typeof myFun is function typeof shape is string typeof size is number typeof today is object typeof dontExist is undefined
For the keywords true
and
null
, the typeof
operator returns the following results:
typeof true is boolean typeof null is object
For a number or string, the typeof
operator returns the following results:
typeof 62 is number typeof 'Hello world' is string
For property values, the typeof
operator returns the type of value the property contains:
typeof document.lastModified is string typeof window.length is number typeof Math.LN2 is number
For methods and functions, the typeof
operator returns results as follows:
typeof blur is function typeof eval is function typeof parseInt is function typeof shape.split is function
For predefined objects, the typeof
operator returns results as follows:
typeof Date is function typeof Function is function typeof Math is function typeof Option is function typeof String is function
The void
operator is used in either
of the following ways:
1. void (expression) 2. void expression
The void
operator specifies an
expression to be evaluated without returning a value.
expression
is a JavaScript expression
to evaluate. The parentheses surrounding the expression are
optional, but it is good style to use them.
You can use the void operator to specify an expression as a hypertext link. The expression is evaluated but is not loaded in place of the current document.
The following code creates a hypertext link that does nothing
when the user clicks it. When the user clicks the link,
void(0)
evaluates to undefined
, which has no effect in JavaScript.
<a href="javascript:void(0)">Click here to do nothing</a>
The following code creates a hypertext link that submits a form when the user clicks it.
<a href="javascript:void(document.form.submit())"> Click here to submit</a>
Table of Contents
You construct a regular expression in one of two ways:
Using a regular expression literal, as follows:
re = /ab+c/;
Calling the constructor function of the RegExp object, as follows:
re = new RegExp("ab+c");
A regular expression pattern is composed of simple characters,
such as /abc/
, or a combination of simple
and special characters, such as /ab*c/
or
/Chapter (\d+)\.\d*/
. The last example
includes parentheses which are used as a memory device. The match
made with this part of the pattern is remembered for later use, as
described in Using Parenthesized
Substring Matches.
Simple patterns are constructed of characters for which you
want to find a direct match. For example, the pattern
/abc/
matches character combinations in
strings only when exactly the characters 'abc' occur together and
in that order. Such a match would succeed in the strings "Hi, do
you know your abc's?" and "The latest airplane designs evolved
from slabcraft." In both cases the match is with the substring
'abc'. There is no match in the string "Grab crab" because it
does not contain the substring 'abc'.
When the search for a match requires something more than a
direct match, such as finding one or more b's, or finding white
space, the pattern includes special characters. For example, the
pattern /ab*c/
matches any character
combination in which a single 'a' is followed by zero or more
'b's (* means 0 or more occurrences of the preceding item) and
then immediately followed by 'c'. In the string "cbbabbbbcdebc,"
the pattern matches the substring 'abbbbc'.
The following table provides a complete list and description of the special characters that can be used in regular expressions.
Character | Meaning |
---|---|
\ |
Either of the following:
|
^ | Matches beginning of input. If the multiline flag is
set to true , also matches
immediately after a line break character. For example,
/^A/ does not match the 'A' in
"an A", but does match the first 'A' in "An A". |
$ | Matches end of input. If the multiline flag is set to
true , also matches immediately
before a line break character. For example, /t$/ does not match the 't' in "eater", but
does match it in "eat". |
* | Matches the preceding character 0 or more times. For
example, /bo*/ matches 'boooo'
in "A ghost booooed" and 'b' in "A bird warbled", but
nothing in "A goat grunted". |
+ | Matches the preceding character 1 or more times.
Equivalent to {1,} . For
example, /a+/ matches the 'a'
in "candy" and all the a's in "caaaaaaandy". |
? |
Matches the preceding character 0 or 1 time.
For example, /e?le?/ matches the 'el' in "angel" and the 'le' in "angle." If used immediately after any of the quantifiers *, +, ?, or {}, makes the quantifier non-greedy (matching the minimum number of times), as opposed to the default, which is greedy (matching the maximum number of times). Also used in lookahead assertions, described underx(?=y) and
x(?!y) in this table.
|
. | (The decimal point) matches any single character
except the newline character. For example, /.n/ matches 'an' and 'on' in "nay, an
apple is on the tree", but not 'nay'. |
(x) | Matches 'x' and remembers the match. These are called
capturing parentheses. For example, /(foo)/ matches and remembers 'foo' in "foo
bar." The matched substring can be recalled from the
resulting array's elements [1], ..., [n]. |
(?:x) | Matches 'x' but does not remember the match. These are called non-capturing parentheses. The matched substring can not be recalled from the resulting array's elements [1], ..., [n]. |
x(?=y) | Matches 'x' only if 'x' is followed by 'y'. For
example, /Jack(?=Sprat)/
matches 'Jack' only if it is followed by 'Sprat'.
/Jack(?=Sprat|Frost)/ matches
'Jack' only if it is followed by 'Sprat' or 'Frost'.
However, neither 'Sprat' nor 'Frost' is part of the match
results. |
x(?!y) | Matches 'x' only if 'x' is not followed by 'y'. For
example, /\d+(?!\.)/ matches a
number only if it is not followed by a decimal point. The
regular expression /\d+(?!\.)/.exec("3.141") matches '141' but
not '3.141'. |
x|y | Matches either 'x' or 'y'. For example, /green|red/ matches 'green' in "green
apple" and 'red' in "red apple." |
{n} | Where n is a positive integer. Matches exactly n
occurrences of the preceding character. For example,
/a{2}/ doesn't match the 'a' in
"candy," but it matches all of the a's in "caandy," and
the first two a's in "caaandy." |
{n,} | Where n is a positive integer. Matches at least n
occurrences of the preceding character. For example,
/a{2,}/ doesn't match the 'a'
in "candy", but matches all of the a's in "caandy" and in
"caaaaaaandy." |
{n,m} | Where n and m are positive integers. Matches at least
n and at most m occurrences of the preceding character.
For example, /a{1,3}/ matches
nothing in "cndy", the 'a' in "candy," the first two a's
in "caandy," and the first three a's in "caaaaaaandy"
Notice that when matching "caaaaaaandy", the match is
"aaa", even though the original string had more a's in
it. |
[xyz] | A character set. Matches any one of the enclosed
characters. You can specify a range of characters by
using a hyphen. For example, [abcd] is the same as [a-d] . They match the 'b' in "brisket" and
the 'c' in "ache". |
[^xyz] | A negated or complemented character set. That is, it
matches anything that is not enclosed in the brackets.
You can specify a range of characters by using a hyphen.
For example, [^abc] is the same as [^a-c] . They initially match 'r' in
"brisket" and 'h' in "chop." |
[\b] | Matches a backspace. (Not to be confused with \b.) |
\b | Matches a word boundary, such as a space or a newline
character. (Not to be confused with [\b] .) For example, /\bn\w/ matches the 'no' in
"noonday";/\wy\b/ matches the
'ly' in "possibly yesterday." |
\B | Matches a non-word boundary. For example,
/\w\Bn/ matches 'on' in
"noonday", and /y\B\w/ matches
'ye' in "possibly yesterday." |
\cX | Where X is a control character. Matches a control
character in a string. For example, /\cM/ matches control-M in a string. |
\d | Matches a digit character. Equivalent to [0-9] . For example, /\d/ or /[0-9]/
matches '2' in "B2 is the suite number." |
\D | Matches any non-digit character. Equivalent to
[^0-9] . For example,
/\D/ or /[^0-9]/ matches 'B' in "B2 is the suite
number." |
\f | Matches a form-feed. |
\n | Matches a linefeed. |
\r | Matches a carriage return. |
\s |
Matches a single white space character, including
space, tab, form feed, line feed. Equivalent to
/\s\w*/ matches ' bar' in
"foo bar."
|
\S |
Matches a single character other than white space.
Equivalent to
/\S\w*/ matches 'foo' in "foo
bar."
|
\t | Matches a tab. |
\v | Matches a vertical tab. |
\w | Matches any alphanumeric character including the
underscore. Equivalent to [A-Za-z0-9_] . For example, /\w/ matches 'a' in "apple," '5' in
"$5.28," and '3' in "3D." |
\W | Matches any non-word character. Equivalent to
[^A-Za-z0-9_] . For example,
/\W/ or /[^A-Za-z0-9_]/ matches '%' in "50%." |
\n | Where n is a positive
integer. A back reference to the last substring matching
the n parenthetical in the
regular expression (counting left parentheses). For
example, /apple(,)\sorange\1/
matches 'apple, orange,' in "apple, orange, cherry,
peach." |
\0 | Matches a NUL character. Do
not follow this with another digit. |
\xhh | Matches the character with the code hh (two hexadecimal digits) |
\uhhhh | Matches the character with the code hhhh (four hexadecimal digits). |
Table 4.1: Special characters in regular expressions.
Parentheses around any part of the regular expression pattern cause that part of the matched substring to be remembered. Once remembered, the substring can be recalled for other use, as described in Using Parenthesized Substring Matches.
For example, the pattern /Chapter
(\d+)\.\d*/
illustrates additional escaped and special
characters and indicates that part of the pattern should be
remembered. It matches precisely the characters 'Chapter '
followed by one or more numeric characters (\d means any numeric
character and + means 1 or more times), followed by a decimal
point (which in itself is a special character; preceding the
decimal point with \
means the pattern
must look for the literal character '.'), followed by any numeric
character 0 or more times (\d
means
numeric character, *
means 0 or more
times). In addition, parentheses are used to remember the first
matched numeric characters.
This pattern is found in "Open Chapter 4.3, paragraph 6" and '4' is remembered. The pattern is not found in "Chapter 3 and 4", because that string does not have a period after the '3'.
To match a substring without causing the matched part to be
remembered, within the parentheses preface the pattern with
?:
. For example, (?:\d+)
matches one or more numeric characters but
does not remember the matched characters.
Regular expressions are used with the RegExp
methods test and exec and with the
String
methods match
, replace
,
search
, and split
. These methods are explained in detail in the
Core JavaScript Reference.
Method | Description |
---|---|
A RegExp method that executes
a search for a match in a string. It returns an array of
information. |
|
A RegExp method that tests
for a match in a string. It returns true or false . |
|
A String method that executes
a search for a match in a string. It returns an array of
information or null on a mismatch. |
|
A String method that tests
for a match in a string. It returns the index of the match,
or -1 if the search fails. |
|
A String method that executes
a search for a match in a string, and replaces the matched
substring with a replacement substring. |
|
A String method that uses a
regular expression or a fixed string to break a string into
an array of substrings. |
Table 4.2: Methods that use regular expressions
When you want to know whether a pattern is found in a string,
use the test or search method; for more information (but slower
execution) use the exec
or match
methods. If you use exec or match and if the
match succeeds, these methods return an array and update properties
of the associated regular expression object and also of the
predefined regular expression object, RegExp
. If the match fails, the exec method returns
null (which converts to false
).
In the following example, the script uses the exec method to find a match in a string.
<script type="text/javascript"> myRe = /d(b+)d/g; myArray = myRe.exec("cdbbdbsbz"); </script>
If you do not need to access the properties of the regular
expression, an alternative way of creating myArray
is with this script:
<script type="text/javascript"> myArray = /d(b+)d/g.exec("cdbbdbsbz"); </script>
If you want to construct the regular expression from a string, yet another alternative is this script:
<script type="text/javascript"> myRe = new RegExp ("d(b+)d", "g"); myArray = myRe.exec("cdbbdbsbz"); </script>
With these scripts, the match succeeds and returns the array and updates the properties shown in the following table.
Object | Property or index | Description | In this example |
---|---|---|---|
myArray | The matched string and all remembered substrings. | ["dbbd", "bb"] | |
index | The 0-based index of the match in the input string. | 1 | |
input | The original string. | "cdbbdbsbz" | |
[0] | The last matched characters. | "dbbd" | |
myRe | lastIndex |
The index at which to start the next match. (This
property is set only if the regular expression uses the g
option, described in
Executing a Global Search, Ignoring Case, and Considering Multiline Input ) |
5 |
source | The text of the pattern. Updated at the time that the regular expression is created, not executed. | "d(b+)d" |
Table 4.3: Results of regular expression execution.
As shown in the second form of this example, you can use a regular expression created with an object initializer without assigning it to a variable. If you do, however, every occurrence is a new regular expression. For this reason, if you use this form without assigning it to a variable, you cannot subsequently access the properties of that regular expression. For example, assume you have this script:
<script type="text/javascript"> myRe = /d(b+)d/g; myArray = myRe.exec("cdbbdbsbz"); document.writeln("The value of lastIndex is " + myRe.lastIndex); </script>
This script displays:
The value of lastIndex is 5
However, if you have this script:
<script type="text/javascript"> myArray = /d(b+)d/g.exec("cdbbdbsbz"); document.writeln("The value of lastIndex is " + /d(b+)d/g.lastIndex); </script>
It displays:
The value of lastIndex is 0
The occurrences of /d(b+)d/g in the two statements are different
regular expression objects and hence have different values for
their lastIndex
property. If you need to
access the properties of a regular expression created with an
object initializer, you should first assign it to a variable.
Including parentheses in a regular expression pattern causes
the corresponding submatch to be remembered. For example,
/a(b)c/
matches the characters 'abc'
and remembers 'b'. To recall these parenthesized substring
matches, use the Array
elements [1],
..., [n].
The number of possible parenthesized substrings is unlimited. The returned array holds all that were found. The following examples illustrate how to use parenthesized substring matches.
Example 1.
The following script uses the replace method to switch the words in the string. For the replacement text, the script uses the $1 and $2 in the replacement to denote the first and second parenthesized substring matches.
<script type="text/javascript"> re = /(\w+)\s(\w+)/; str = "John Smith"; newstr = str.replace(re, "$2, $1"); document.write(newstr); </script>
This prints "Smith, John".
Example 2.
Note: in the getInfo
function, the
exec method is called using the ()
shortcut notation that works in Firefox but not in most other
browsers.
<script type="text/javascript"> function getInfo(field){ var a = /(\w+)\s(\d+)/(field.value); window.alert(a[1] + ", your age is " + a[2]); } </script> <p>Enter your first name and your age, and then press Enter.</p> <form> <input type="text" name="NameAge" onchange="getInfo(this);"> </form>
Regular expressions have three optional flags that allow for
global and case insensitive searching. To indicate a global
search, use the g
flag. To indicate a
case-insensitive search, use the i
flag. To indicate a multi-line search, use the m
flag. These flags can be used separately or
together in any order, and are included as part of the regular
expression.
To include a flag with the regular expression, use this syntax:
re = /pattern/flags re = new RegExp("pattern", ["flags"])
Note that the flags are an integral part of a regular expression. They cannot be added or removed later.
For example, re = /\w+\s/g
creates a
regular expression that looks for one or more characters followed
by a space, and it looks for this combination throughout the
string.
<script type="text/javascript"> re = /\w+\s/g; str = "fee fi fo fum"; myArray = str.match(re); document.write(myArray); </script>
This displays ["fee ", "fi ", "fo "]. In this example, you could replace the line:
re = /\w+\s/g;
with:
re = new RegExp("\\w+\\s", "g");
and get the same result.
The m flag is used to specify that a multiline input string
should be treated as multiple lines. If the m flag is used,
^
and $
match
at the start or end of any line within the input string instead
of the start or end of the entire string.
The following examples show some uses of regular expressions.
The following example illustrates the formation of regular
expressions and the use of string.split()
and string.replace()
. It cleans a roughly formatted
input string containing names (first name first) separated by
blanks, tabs and exactly one semicolon. Finally, it reverses
the name order (last name first) and sorts the list.
<script type="text/javascript"> // The name string contains multiple spaces and tabs, // and may have multiple spaces between first and last names. var names = "Harry Trump ;Fred Barney; Helen Rigby ; Bill Abel ; Chris Hand "; var output = new Array( "---------- Original String<br><br>", names + "<br><br>"); // Prepare two regular expression patterns and array storage. // Split the string into array elements. // pattern: possible white space then semicolon then possible white space var pattern = /\s*;\s*/; // Break the string into pieces separated by the pattern above and // store the pieces in an array called nameList var nameList = names.split(pattern); // new pattern: one or more characters then spaces then characters. // Use parentheses to "memorize" portions of the pattern. // The memorized portions are referred to later. var pattern = /(\w+)\s+(\w+)/; // New array for holding names being processed. var bySurnameList = new Array(); // Display the name array and populate the new array // with comma-separated names, last first. // // The replace method removes anything matching the pattern // and replaces it with the memorized string - second memorized portion // followed by comma space followed by first memorized portion. // // The variables $1 and $2 refer to the portions // memorized while matching the pattern. output.push("---------- After Split by Regular Expression<br>"); var i, len; for (i = 0, len = nameList.length; i < len; i++) { output.push(nameList[i] + "<br>"); bySurnameList[i] = nameList[i].replace(pattern, "$2, $1") } // Display the new array. output.push("---------- Names Reversed<br>"); for (i = 0, len = bySurnameList.length; i < len; i++) { output.push(bySurnameList[i] + "<br>") } // Sort by last name, then display the sorted array. bySurnameList.sort(); output.push("---------- Sorted<br>"); for (i = 0, len = bySurnameList.length; i < len; i++) { output.push(bySurnameList[i] + "<br>") } output.push("---------- End<br>"); document.write(output.join("\n")); </script>
In the following example, a user enters a phone number. When the user presses Enter, the script checks the validity of the number. If the number is valid (matches the character sequence specified by the regular expression), the script posts a window thanking the user and confirming the number. If the number is invalid, the script posts a window informing the user that the phone number is not valid.
The regular expression looks for zero or one open
parenthesis \(?
, followed by three
digits \d{3}
, followed by zero or one
close parenthesis \)?
, followed by
one dash, forward slash, or decimal point and when found,
remember the character ([-\/\.])
,
followed by three digits \d{3}
,
followed by the remembered match of a dash, forward slash, or
decimal point \1
, followed by four
digits \d{4}
.
The onchange
event is activated
when the user presses Enter to send the form, and sets the
value of RegExp.input
.
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1"> <meta http-equiv="Content-Script-Type" content="text/javascript"> <script type="text/javascript"> var re = /\(?\d{3}\)?([-\/\.])\d{3}\1\d{4}/; function testInfo(phoneInput) { var OK = re.exec(phoneInput.value); if (!OK) { window.alert(RegExp.input + " isn't a phone number with area code!"); } else { window.alert("Thanks, your phone number is " + OK[0]); } } </script> </head> <body> <p>Enter your phone number (with area code) and then press Enter.</p> <form action=""> <input name="phone" onchange="testInfo(this);"> </form> </body> </html>
Table of Contents
A block statement is used to group statements. The block is delimited by a pair of curly brackets:
{ statement_1 statement_2 . . . statement_n }
Example
Block statements are commonly used with control flow statements (e.g. if, for, while).
while (x < 10) { x++; }
Here, { x++; } is the block statement.
Important: JavaScript does not have block scope. Variables introduced with a block are scoped to the containing function or script, and the effects of setting them persist beyond the block itself. In other words, block statements do not introduce a scope. Although "standalone" blocks are valid syntax, you do not want to use standalone blocks in JavaScript, because they don't do what you think they do, if you think they do anything like such blocks in C or Java. For example:
var x = 1; { var x = 2; } alert(x); // outputs 2
This outputs 2 because the var x
statement within the block is in the same scope as the var x
statement before the block. In C or Java, the
equivalent code would have outputted 1.
A conditional statement is a set of commands that executes if a
specified condition is true
. JavaScript
supports two conditional statements: if...else and switch.
Use the if
statement to execute a
statement if a logical condition is true
. Use the optional else
clause to execute a statement if the condition
is false
. An if
statement looks as follows:
if (condition) statement_1 [else statement_2]
condition
can be any expression that
evaluates to true
or false
. If condition
evaluates to true
, statement_1
is executed; otherwise, statement_2
is executed. statement_1
and statement_2
can be any statement, including further
nested if
statements.
You may also compound the statements using else if to have multiple conditions tested in sequence, as follows:
if (condition) statement_1 [else if (condition_2) statement_2] ... [else if (condition_n_1) statement_n_1] [else statement_n]
To execute multiple statements, use a block statement
({ ... }
) to group those statements. In
general, it is a good practice to always use block statements,
especially in code involving nested if statements:
if (condition) { statements_1 } else { statements_2 }
It is advisable to not use simple assignments in a conditional expression, because the assignment can be confused with equality when glancing over the code. For example, do not use the following code:
if (x = y) { /* do the right thing */ }
If you need to use an assignment in a conditional expression, a common practice is to put additional parentheses around the assignment. For example:
if ((x = y)) { /* do the right thing */ }
Do not confuse the primitive boolean values true
and false
with the
true
and false
values of the Boolean
object. Any value that is not undefined
, null
,
0
, NaN
, or
the empty string (""
), and any object,
including a Boolean
object whose value
is false
, evaluates to true
when passed to a conditional statement. For
example:
var b = new Boolean(false); if (b) // this condition evaluates to true
In the following example, the function checkData
returns true
if
the number of characters in a Text
object is three; otherwise, it displays an alert and returns
false
.
function checkData() { if (document.form1.threeChar.value.length == 3) { return true; } else { alert("Enter exactly three characters. " + document.form1.threeChar.value + " is not valid."); return false; } }
A switch
statement allows a program
to evaluate an expression and attempt to match the expression's
value to a case label. If a match is found, the program executes
the associated statement. A switch
statement looks as follows:
switch (expression) { case label_1: statements_1 [break;] case label_2: statements_2 [break;] ... default: statements_def [break;] }
The program first looks for a case
clause with a label matching the value of expression and then
transfers control to that clause, executing the associated
statements. If no matching label is found, the program looks for
the optional default
clause, and if
found, transfers control to that clause, executing the associated
statements. If no default clause is found, the program continues
execution at the statement following the end of switch. By
convention, the default
clause is the
last clause, but it does not need to be so.
The optional break statement associated with each case clause ensures that the program breaks out of switch once the matched statement is executed and continues execution at the statement following switch. If break is omitted, the program continues execution at the next statement in the switch statement.
Example
In the following example, if fruittype
evaluates to "Bananas"
, the program matches the value with case
"Bananas"
and executes the associated
statement. When break
is encountered,
the program terminates switch and executes the statement
following switch. If break were omitted, the statement for case
"Cherries" would also be executed.
switch (fruittype) { case "Oranges": document.write("Oranges are $0.59 a pound.<br>"); break; case "Apples": document.write("Apples are $0.32 a pound.<br>"); break; case "Bananas": document.write("Bananas are $0.48 a pound.<br>"); break; case "Cherries": document.write("Cherries are $3.00 a pound.<br>"); break; case "Mangoes": case "Papayas": document.write("Mangoes and papayas are $2.79 a pound.<br>"); break; default: document.write("Sorry, we are out of " + fruittype + ".<br>"); } document.write("Is there anything else you'd like?<br>");
A loop is a set of commands that executes repeatedly until a
specified condition is met. JavaScript supports the for
, do while
, and
while
loop statements, as well as
label
(label
is
not itself a looping statement, but is frequently used with these
statements). In addition, you can use the break
and continue
statements within loop
statements.
Another statement, for...in
, executes
statements repeatedly but is used for object manipulation. See
Object Manipulation
Statements.
The loop statements are:
A for
loop repeats until a specified
condition evaluates to false
. The
JavaScript for
loop is similar to the
Java and C for loop. A for statement looks as follows:
for ([initialExpression]; [condition]; [incrementExpression]) statement
When a for loop executes, the following occurs:
The initializing expression initialExpression
, if any, is executed. This
expression usually initializes one or more loop counters,
but the syntax allows an expression of any degree of
complexity. This expression can also declare variables.
The condition expression is evaluated. If the value of
condition is true
, the loop
statements execute. If the value of condition is
false
, the for
loop terminates. If the condition
expression is omitted entirely, the condition is assumed to
be true
.
The statement executes. To execute multiple statements,
use a block statement ({ ... }
)
to group those statements.
The update expression incrementExpression
, if there is one,
executes, and control returns to step 2.
Example
The following function contains a for
statement that counts the number of selected
options in a scrolling list (a select
object that allows multiple selections). The for
statement declares the variable i
and initializes it to zero. It checks that i is
less than the number of options in the select
object, performs the succeeding if
statement, and increments i by one after each
pass through the loop.
<script type="text/javascript">//<![CDATA[ function howMany(selectObject) { var numberSelected = 0; for (var i = 0; i < selectObject.options.length; i++) { if (selectObject.options[i].selected) numberSelected++; } return numberSelected; } //]]></script> <form name="selectForm"> <p> <strong>Choose some music types, then click the button below:</strong> <br/> <select name="musicTypes" multiple="multiple"> <option selected="selected">R&B</option> <option>Jazz</option> <option>Blues</option> <option>New Age</option> <option>Classical</option> <option>Opera</option> </select> </p> <p> <input type="button" value="How many are selected?" onclick="alert ('Number of options selected: ' + howMany(document.selectForm.musicTypes))"/> </p> </form>
The do...while
statement repeats
until a specified condition evaluates to false
. A do...while
statement looks as follows:
do statement while (condition);
statement executes once before the condition is checked. To
execute multiple statements, use a block statement ({ ... }
) to group those statements. If condition is
true
, the statement executes again. At
the end of every execution, the condition is checked. When the
condition is false
, execution stops and
control passes to the statement following do...while
.
Example
In the following example, the do loop iterates at least once and reiterates until i is no longer less than 5.
do { i += 1; document.write(i); } while (i < 5);
A while
statement executes its
statements as long as a specified condition evaluates to
true
. A while statement looks as
follows:
while (condition) statement
If the condition becomes false
,
statement within the loop stops executing and control passes to
the statement following the loop.
The condition test occurs before statement in the loop are
executed. If the condition returns true
, statement is executed and the condition is
tested again. If the condition returns false
, execution stops and control is passed to the
statement following while.
To execute multiple statements, use a block statement ({ ... }) to group those statements.
Example 1.
The following while loop iterates as long as n is less than three:
n = 0; x = 0; while (n < 3) { n++; x += n; }
With each iteration, the loop increments n and adds that value to x. Therefore, x and n take on the following values:
After the first pass: n = 1 and x = 1
After the second pass: n = 2 and x = 3
After the third pass: n = 3 and x = 6
After completing the third pass, the condition n < 3 is no
longer true
, so the loop
terminates.
Example 2.
Avoid infinite loops. Make sure the condition in a loop
eventually becomes false
; otherwise,
the loop will never terminate. The statements in the following
while
loop execute forever because the
condition never becomes false
:
while (true) { alert("Hello, world"); }
A label
provides a statement with an
identifier that lets you refer to it elsewhere in your program.
For example, you can use a label to identify a loop, and then use
the break
or continue
statements to indicate whether a program
should interrupt the loop or continue its execution.
The syntax of the label
statement
looks like the following:
label: statement
The value of label may be any JavaScript identifier that is not a reserved word. The statement that you identify with a label may be any statement.
Example
In this example, the label
markLoop
identifies a while
loop.
markLoop: while (theMark == true) doSomething(); }
Use the break
statement to terminate
a loop, switch, or label statement.
When you use break
without a
label
, it terminates the
innermost enclosing while
,
do-while
, for
, or switch
immediately and transfers control to the following
statement.
When you use break
with a
label
, it terminates the
specified labeled statement.
The syntax of the break statement looks like this:
break;
break label;
The first form of the syntax terminates the innermost enclosing loop or switch; the second form of the syntax terminates the specified enclosing label statement.
Example
The following example iterates through the elements in an array until it finds the index of an element whose value is theValue:
for (i = 0; i < a.length; i++) { if (a[i] == theValue) break; }
The continue
statement can be used
to restart a while, do-while, for, or label statement.
When you use continue
without
a label
, it terminates the
current iteration of the innermost enclosing while
, do-while
or
for
statement and continues
execution of the loop with the next iteration. In contrast
to the break
statement,
continue
does not terminate the
execution of the loop entirely. In a while
loop, it jumps back to the condition.
In a for
loop, it jumps to the
increment-expression.
When you use continue
with a
label, it applies to the looping statement identified with
that label.
The syntax of the continue statement looks like the following:
continue;
continue label;
Example 1.
The following example shows a while
loop with a continue
statement that
executes when the value of i is three. Thus, n
takes on the values one, three, seven, and
twelve.
i = 0; n = 0; while (i < 5) { i++; if (i == 3) continue; n += i; }
Example 2.
A statement labeled checkiandj
contains a statement labeled checkj
. If
continue
is encountered, the program
terminates the current iteration of checkj
and begins the next iteration. Each time
continue
is encountered, checkj
reiterates until its condition returns
false
. When false
is returned, the remainder of the
checkiandj
statement is completed, and
checkiandj
reiterates until its
condition returns false
. When
false
is returned, the program
continues at the statement following checkiandj
.
If continue had a label of checkiandj
, the program would continue at the top
of the checkiandj
statement.
checkiandj : while (i < 4) { document.write(i + "<br/>"); i += 1; checkj : while (j > 4) { document.write(j + "<br/>"); j -= 1; if ((j % 2) == 0) continue checkj; document.write(j + " is odd.<br/>"); } document.write("i = " + i + "<br/>"); document.write("j = " + j + "<br/>"); }
JavaScript uses the for...in
,
for each...in
, and with
statements to manipulate objects.
The for...in statement iterates a specified
variable over all the properties of an object. For each distinct
property, JavaScript executes the specified statements. A
for...in
statement looks as
follows:
for (variable in object) { statements }
Example
The following function takes as its argument an object and the object's name. It then iterates over all the object's properties and returns a string that lists the property names and their values.
function dump_props(obj, obj_name) { var result = ""; for (var i in obj) { result += obj_name + "." + i + " = " + obj[i] + "<br>"; } result += "<hr>"; return result; }
For an object car with properties make and model, result would be:
car.make = Ford car.model = Mustang
Arrays Although it
may be tempting to use this as a way to iterate over Array elements, because the for...in
statement iterates over user-defined
properties in addition to the array elements, if you modify the
Array
object, such as adding custom
properties or methods, the for...in
statement will return the name of your user-defined properties in
addition to the numeric indexes. Thus it is better to use a
traditional for loop with a numeric index when iterating
over arrays.
for each...in is a loop statement introduced in
JavaScript 1.6. It is similar to for...in
, but iterates over the values of object's
properties, not their names.
The with statement establishes the default object for a set of statements. JavaScript looks up any unqualified names within the set of statements to determine if the names are properties of the default object. If an unqualified name matches a property, then the property is used in the statement; otherwise, a local or global variable is used.
A with statement looks as follows:
with (object) { statements }
Example
The following with statement specifies that the Math
object is the default object. The statements
following the with statement refer to the PI
property and the cos
and sin
methods, without specifying an
object. JavaScript assumes the Math
object for these references.
var a, x, y; var r = 10; with (Math) { a = PI * r * r; x = r * cos(PI); y = r * sin(PI/2); }
Note: While using a with
statement
can make your program more concise, improper use of with
can significantly slow down your program. See
with.
Comments are author notations that explain what a script does. Comments are ignored by the interpreter. JavaScript supports Java and C++-style comments:
Comments on a single line are preceded by a double-slash (//).
Comments that span multiple lines are preceded by /* and followed by */:
Example
The following example shows two comments:
// This is a single-line comment. /* This is a multiple-line comment. It can be of any length, and you can put whatever you want here. */
You can throw exceptions using the throw
statement and handle them using the
try...catch
statements.
Just about any object can be thrown in JavaScript. Nevertheless, not all thrown objects are created equal. While it is fairly common to throw numbers or strings as errors it is frequently more effective to use one of the exception types specifically created for this purpose:
ECMAScript exceptions:
Error
EvalError
RangeError
ReferenceError
SyntaxError
TypeError
URIError
DOM exceptions:
DOMException
EventException
RangeException
... (?)
nsIXPCException (XPConnect)
Use the throw
statement to throw an
exception. When you throw an exception, you specify an expression
containing the value of the exception:
throw expression
The following code throws several exceptions.
throw "Error2"; // generates an exception with a string value throw 42; // generates an exception with the value 42 throw true; // generates an exception with the value true
You can specify an object when you throw an exception. You can
then reference the object's properties in the catch
block. The following example creates an
object myUserException
of type
UserException and uses it in a throw
statement.
// Create an object type UserException function UserException (message) { this.message=message; this.name="UserException"; } // Create an instance of the object type and throw it myUserException=new UserException("Value too high"); throw myUserException;
The try...catch
statement marks a
block of statements to try, and specifies one or more responses
should an exception be thrown. If an exception is thrown, the
try...catch
statement catches it.
The try...catch
statement consists
of a try block, which contains one or more statements, and zero
or more catch
blocks, containing
statements that specify what to do if an exception is thrown in
the try
block. That is, you want the
try
block to succeed, and if it does
not succeed, you want control to pass to the catch
block. If any statement within the
try
block (or in a function called from
within the try
block) throws an
exception, control immediately shifts to the catch
block. If no exception is thrown in the
try
block succeed, the catch
block is skipped. The finally
block executes after the try and
catch
blocks execute but before the
statements following the try...catch
statement.
The following example uses a try...catch
statement. The example calls a function
that retrieves a month name from an array based on the value
passed to the function. If the value does not correspond to a
month number (1-12), an exception is thrown with the value
InvalidMonthNo and the statements in the catch
block set the monthName variable to
unknown.
function getMonthName (mo) { mo=mo-1; // Adjust month number for array index (1=Jan, 12=Dec) var months=new Array("Jan","Feb","Mar","Apr","May","Jun","Jul", "Aug","Sep","Oct","Nov","Dec"); if (months[mo] != null) { return months[mo] } else { throw "InvalidMonthNo" } } try { // statements to try monthName=getMonthName(myMonth) // function could throw exception } catch (e) { monthName="unknown" logMyErrors(e) // pass exception object to error handler }
You can use a single catch
block
to handle all exceptions that may be generated in the
try
block, or you can use separate
catch
blocks each of which handles a
particular type of exception.
Single catch
Block Use a single try...catch
statement's catch
block (recovery block) to execute
error-handling code for any exceptions thrown in the
try
block.
A single catch
block has the
following syntax:
catch (catchID) { statements }
The catch
block specifies an
identifier (catchID
in the preceding
syntax) that holds the value specified by the throw
statement; you can use this identifier to
get information about the exception that was thrown. JavaScript
creates this identifier when the catch
block is entered; the identifier lasts only
for the duration of the catch
block;
after the catch
block finishes
executing, the identifier is no longer available.
For example, the following code throws an exception. When the exception occurs, control transfers to the catch block.
try { throw "myException" // generates an exception } catch (e) { // statements to handle any exceptions logMyErrors(e) // pass exception object to error handler }
Multiple catch
Blocks A single try statement can contain
multiple conditional catch
blocks,
each of which handles a specific type of exception. In this
case, the appropriate conditional catch
block is entered only when the exception
specified for that block is thrown. You can also include an
optional catch-all catch
block for
all unspecified exceptions as the final catch
block in the statement.
For example, the following function invokes three other functions (declared elsewhere), which validate its arguments. If a validation function determines that the component that it is checking is invalid, it returns 0, causing the caller to throw a particular exception.
function getCustInfo(name, id, email) { var n, i, e; if (!validate_name(name)) throw "InvalidNameException" else n = name; if (!validate_id(id)) throw "InvalidIdException" else i = id; if (!validate_email(email)) throw "InvalidEmailException" else e = email; cust = (n + " " + i + " " + e); return (cust); }
The conditional catch
blocks route
control to the appropriate exception handler.
try { // function could throw three exceptions getCustInfo("Lee", 1234, "lee@netscape.com") } catch (e if e == "InvalidNameException") { // call handler for invalid names bad_name_handler(e) } catch (e if e == "InvalidIdException") { // call handler for invalid ids bad_id_handler(e) } catch (e if e == "InvalidEmailException") { // call handler for invalid email addresses bad_email_handler(e) } catch (e){ // don't know what to do, but log it logError(e) }
The finally
block contains
statements to execute after the try and catch
blocks execute but before the statements
following the try...catch
statement.
The finally
block executes whether or
not an exception is thrown. If an exception is thrown, the
statements in the finally
block
execute even if no catch
block
handles the exception.
You can use the finally
block to
make your script fail gracefully when an exception occurs; for
example, you may need to release a resource that your script
has tied up. The following example opens a file and then
executes statements that use the file (server-side JavaScript
allows you to access files). If an exception is thrown while
the file is open, the finally
block
closes the file before the script fails.
openMyFile(); try { writeMyFile(theData); //This may throw a error }catch(e){ handleError(e); // If we got a error we handle it }finally { closeMyFile(); // always close the resource }
Table of Contents
A function definition consists of the function keyword, followed by
The name of the function.
A list of arguments to the function, enclosed in parentheses and separated by commas.
The JavaScript statements that define the function, enclosed in curly braces, { }. The statements in a function can include calls to other functions defined in the current application.
For example, the following code defines a simple function named square:
function square(number) { return number * number; }
The function square takes one argument, called number. The function consists of one statement that indicates to return the argument of the function multiplied by itself. The return statement specifies the value returned by the function.
return number * number
All parameters are passed to functions by value; the value is passed to the function, but if the function changes the value of the parameter, this change is not reflected globally or in the calling function. However, if you pass an object as a parameter to a function and the function changes the object's properties, that change is visible outside the function, as shown in the following example:
function myFunc(theObject) { theObject.make="Toyota" } mycar = {make:"Honda", model:"Accord", year:1998}; x=mycar.make; // returns Honda myFunc(mycar); // pass object mycar to the function y=mycar.make; // returns Toyota (prop was changed by the function)
A function can be defined based on a condition. For example, given the following function definition:
if (num == 0) { function myFunc(theObject) { theObject.make="Toyota" } }
the myFunc
function is only defined if
the variable num equals 0. If num does not equal 0, the function is
not defined, and any attempt to execute it will fail.
In addition to defining functions as described here, you can also define Function Object.
A method is a function associated with an object. You'll learn more about objects and methods in Working with Objects.
A function can also be defined inside an expression. This is called a function expression. Typically such a function is anonymous; it does not have to have a name. For example, the function square could have been defined as:
const square = function(number) {return number * number};
This is convenient when passing a function as an argument to another function. The following example shows the map function being defined and then called with an anonymous function as its first parameter:
function map(f,a) { var result=new Array; for (var i = 0; i != a.length; i++) result[i] = f(a[i]); return result; }
The call
map(function(x) {return x * x * x}, [0, 1, 2, 5, 10]);
returns [0, 1, 8, 125, 1000].
Defining a function does not execute it. Defining the function
simply names the function and specifies what to do when the
function is called. Calling
the function actually performs the specified actions with the
indicated parameters. For example, if you define the function
square
, you could call it as follows.
square(5)
The preceding statement calls the function with an argument of five. The function executes its statements and returns the value twenty-five.
The arguments of a function are not limited to strings and
numbers. You can pass whole objects to a function, too. The
show_props
function (defined in Objects and Properties) is an example
of a function that takes an object as an argument.
A function can even be recursive, that is, it can call itself. For example, here is a function that computes factorials:
function factorial(n) { if ((n == 0) || (n == 1)) return 1; else { var result = (n * factorial(n-1) ); return result; } }
You could then compute the factorials of one through five as follows:
a=factorial(1); // returns 1 b=factorial(2); // returns 2 c=factorial(3); // returns 6 d=factorial(4); // returns 24 e=factorial(5); // returns 120
The arguments of a function are maintained in an array-like object. Within a function, you can address the arguments passed to it as follows:
arguments[i]
where i is the ordinal number of the argument, starting at zero. So, the first argument passed to a function would be arguments[0]. The total number of arguments is indicated by arguments.length.
Using the arguments object, you can call a function with more arguments than it is formally declared to accept. This is often useful if you don't know in advance how many arguments will be passed to the function. You can use arguments.length to determine the number of arguments actually passed to the function, and then treat each argument using the arguments object.
For example, consider a function that concatenates several strings. The only formal argument for the function is a string that specifies the characters that separate the items to concatenate. The function is defined as follows:
function myConcat(separator) { var result = ""; // initialize list // iterate through arguments for (var i = 1; i < arguments.length; i++) { result += arguments[i] + separator; } return result; }
You can pass any number of arguments to this function, and it concatenates each argument into a string "list":
// returns "red, orange, blue, " myConcat(", ", "red", "orange", "blue"); // returns "elephant; giraffe; lion; cheetah; " myConcat("; ", "elephant", "giraffe", "lion", "cheetah"); // returns "sage. basil. oregano. pepper. parsley. " myConcat(". ", "sage", "basil", "oregano", "pepper", "parsley");
See the Function in the Core JavaScript Reference for more information.
JavaScript 1.3 and earlier versions The arguments object is a property of the Function object and can be preceded by the function name, as follows:
functionName.arguments[i]
JavaScript has several top-level predefined functions:
The eval function evaluates a string of JavaScript code without reference to a particular object. The syntax of eval is:
eval(expr)
where expr
is a string to be
evaluated.
If the string represents an expression, eval evaluates the expression. If the argument represents one or more JavaScript statements, eval performs the statements. The scope of eval code is identical to the scope of the calling code. Do not call eval to evaluate an arithmetic expression; JavaScript evaluates arithmetic expressions automatically.
The isFinite
function evaluates an
argument to determine whether it is a finite number. The syntax
of isFinite
is:
isFinite(number)
where number is the number to evaluate.
If the argument is NaN
, positive
infinity or negative infinity, this method returns false
, otherwise it returns true
.
The following code checks client input to determine whether it is a finite number.
if(isFinite(ClientInput)) { /* take specific steps */ }
The isNaN
function evaluates an
argument to determine if it is NaN
(not
a number). The syntax of isNaN
is:
isNaN(testValue)
where testValue is the value you want to evaluate.
The parseFloat
and parseInt
functions return NaN
when they evaluate a value that is not a
number. isNaN
returns true
if passed NaN
, and
false
otherwise.
The following code evaluates floatValue
to determine if it is a number and then
calls a procedure accordingly:
floatValue=parseFloat(toFloat) if (isNaN(floatValue)) { notFloat() } else { isFloat() }
The two "parse" functions, parseInt
and parseFloat
, return a numeric value
when given a string as an argument.
The syntax of parseFloat
is
parseFloat(str)
where parseFloat
parses its
argument, the string str, and attempts to return a floating-point
number. If it encounters a character other than a sign (+ or -),
a numeral (0-9), a decimal point, or an exponent, then it returns
the value up to that point and ignores that character and all
succeeding characters. If the first character cannot be converted
to a number, it returns NaN
(not a
number).
The syntax of parseInt is
parseInt(str [, radix])
parseInt
parses its first argument,
the string str
, and attempts to return
an integer of the specified radix (base), indicated by the
second, optional argument, radix. For example, a radix of ten
indicates to convert to a decimal number, eight octal, sixteen
hexadecimal, and so on. For radixes above ten, the letters of the
alphabet indicate numerals greater than nine. For example, for
hexadecimal numbers (base 16), A through F are used.
If parseInt
encounters a character
that is not a numeral in the specified radix, it ignores it and
all succeeding characters and returns the integer value parsed up
to that point. If the first character cannot be converted to a
number in the specified radix, it returns NaN
. The parseInt
function truncates the string to integer values.
The Number
and String
functions let you convert an object to a
number or a string. The syntax of these functions is:
Number(objRef) String(objRef)
where objRef
is an object
reference.
The following example converts the Date object to a readable string.
D = new Date (430054663215) // The following returns // "Thu Aug 18 04:37:43 GMT-0700 (Pacific Daylight Time) 1983" x = String(D)
The escape and unescape functions let you encode and decode strings. The escape function returns the hexadecimal encoding of an argument in the ISO Latin character set. The unescape function returns the ASCII string for the specified hexadecimal encoding value.
The syntax of these functions is:
escape(string) unescape(string)
These functions are used primarily with server-side JavaScript to encode and decode name/value pairs in URLs.
The escape and unescape functions do not work properly for non-ASCII characters and have been deprecated. In JavaScript 1.5 and later, use encodeURI, decodeURI, encodeURIComponent, and decodeURIComponent.
Table of Contents
A JavaScript object has properties associated with it. You access the properties of an object with a simple notation:
objectName.propertyName
Both the object name and property name are case sensitive. You
define a property by assigning it a value. For example, suppose
there is an object named myCar
(for now,
just assume the object already exists). You can give it properties
named make, model, and year as follows:
myCar.make = "Ford"; myCar.model = "Mustang"; myCar.year = 1969;
An array is an ordered set of values associated with a single variable name. Properties and arrays in JavaScript are intimately related; in fact, they are different interfaces to the same data structure. So, for example, you could access the properties of the myCar object as follows:
myCar["make"] = "Ford"; myCar["model"] = "Mustang"; myCar["year"] = 1967;
This type of array is known as an associative array, because each index element is also associated with a string value. To illustrate how this works, the following function displays the properties of the object when you pass the object and the object's name as arguments to the function:
function show_props(obj, obj_name) { var result = ""; for (var i in obj) result += obj_name + "." + i + " = " + obj[i] + "\n"; return result; }
So, the function call show_props(myCar, "myCar") would return the following:
myCar.make = Ford myCar.model = Mustang myCar.year = 1967
JavaScript has a number of predefined objects. In addition, you can create your own objects. In JavaScript 1.2 and later, you can create an object using an object initializer. Alternatively, you can first create a constructor function and then instantiate an object using that function and the new operator.
In addition to creating objects using a constructor function, you can create objects using an object initializer. Using object initializers is sometimes referred to as creating objects with literal notation. "Object initializer" is consistent with the terminology used by C++.
The syntax for an object using an object initializer is:
objectName = {property_1:value_1, property_2:value_2, ..., property_n:value_n}
where objectName
is the name of the
new object, each property I is an identifier (either a name, a
number, or a string literal), and each value I is an expression whose value is
assigned to the property I. The objectName
and assignment is optional. If you do
not need to refer to this object elsewhere, you do not need to
assign it to a variable.
If an object is created with an object initializer in a top-level script, JavaScript interprets the object each time it evaluates an expression containing the object literal. In addition, an initializer used in a function is created each time the function is called.
The following statement creates an object and assigns it to
the variable x if and only if the expression cond is true
.
if (cond) x = {hi:"there"};
The following example creates myHonda
with three properties. Note that the engine
property is also an object with its own properties.
myHonda = {color:"red",wheels:4,engine:{cylinders:4,size:2.2}};
You can also use object initializers to create arrays. See Array Literals.
JavaScript 1.1 and earlier. You cannot use object initializers. You can create objects only using their constructor functions or using a function supplied by some other object for that purpose. See Using a Constructor Function.
Alternatively, you can create an object with these two steps:
Define the object type by writing a constructor function.
Create an instance of the object with new.
To define an object type, create a function for the object type that specifies its name, properties, and methods. For example, suppose you want to create an object type for cars. You want this type of object to be called car, and you want it to have properties for make, model, and year. To do this, you would write the following function:
function car(make, model, year) { this.make = make; this.model = model; this.year = year; }
Notice the use of this to assign values to the object's properties based on the values passed to the function.
Now you can create an object called mycar as follows:
mycar = new car("Eagle", "Talon TSi", 1993);
This statement creates mycar
and
assigns it the specified values for its properties. Then the
value of mycar.make
is the string
"Eagle"
, mycar.year
is the integer 1993, and so on.
You can create any number of car objects by calls to new. For example,
kenscar = new car("Nissan", "300ZX", 1992); vpgscar = new car("Mazda", "Miata", 1990);
An object can have a property that is itself another object. For example, suppose you define an object called person as follows:
function person(name, age, sex) { this.name = name; this.age = age; this.sex = sex; }
and then instantiate two new person objects as follows:
rand = new person("Rand McKinnon", 33, "M"); ken = new person("Ken Jones", 39, "M");
Then you can rewrite the definition of car to include an owner property that takes a person object, as follows:
function car(make, model, year, owner) { this.make = make; this.model = model; this.year = year; this.owner = owner; }
To instantiate the new objects, you then use the following:
car1 = new car("Eagle", "Talon TSi", 1993, rand); car2 = new car("Nissan", "300ZX", 1992, ken);
Notice that instead of passing a literal string or integer value when creating the new objects, the above statements pass the objects rand and ken as the arguments for the owners. Then if you want to find out the name of the owner of car2, you can access the following property:
car2.owner.name
Note that you can always add a property to a previously defined object. For example, the statement
car1.color = "black"
adds a property color to car1, and assigns it a value of "black." However, this does not affect any other objects. To add the new property to all objects of the same type, you have to add the property to the definition of the car object type.
In JavaScript 1.0, you can refer to an object's properties by their property name or by their ordinal index. In JavaScript 1.1 or later, however, if you initially define a property by its name, you must always refer to it by its name, and if you initially define a property by an index, you must always refer to it by its index.
This applies when you create an object and its properties with
a constructor function, as in the above example of the Car object
type, and when you define individual properties explicitly (for
example, myCar.color = "red"
). So if
you define object properties initially with an index, such as
myCar[5] = "25 mpg"
, you can
subsequently refer to the property as myCar[5]
.
The exception to this rule is objects reflected from HTML,
such as the forms array. You can always refer to objects in these
arrays by either their ordinal number (based on where they appear
in the document) or their name (if defined). For example, if the
second form
tag in a document has a
name
attribute with value "myForm"
, you can refer to the form as document.forms[1]
or document.forms["myForm"]
or document.myForm
.
You can add a property to a previously defined object type by using the prototype property. This defines a property that is shared by all objects of the specified type, rather than by just one instance of the object. The following code adds a color property to all objects of type car, and then assigns a value to the color property of the object car1.
Car.prototype.color=null; car1.color="black";
See the Function object in the Core JavaScript Reference> for more information.
A method is a function associated with an object. You define a method the same way you define a standard function. Then you use the following syntax to associate the function with an existing object:
object.methodname = function_name
where object is an existing object, methodname is the name you are assigning to the method, and function_name is the name of the function.
You can then call the method in the context of the object as follows:
object.methodname(params);
You can define methods for an object type by including a method definition in the object constructor function. For example, you could define a function that would format and display the properties of the previously-defined car objects; for example,
function displayCar() { var result = "A Beautiful " + this.year + " " + this.make + " " + this.model; pretty_print(result); }
where pretty_print
is function to
display a horizontal rule and a string. Notice the use of this to
refer to the object to which the method belongs.
You can make this function a method of car by adding the statement
this.displayCar = displayCar;
to the object definition. So, the full definition of car would now look like
function car(make, model, year, owner) { this.make = make; this.model = model; this.year = year; this.owner = owner; this.displayCar = displayCar; }
Then you can call the displayCar
method for each of the objects as follows:
car1.displayCar() car2.displayCar()
This produces the output shown in the following figure.
Figure 7.1: Displaying method output
JavaScript has a special keyword, this, that you can use within a method to refer to the current object. For example, suppose you have a function called validate that validates an object's value property, given the object and the high and low values:
function validate(obj, lowval, hival) { if ((obj.value < lowval) || (obj.value > hival)) alert("Invalid Value!"); }
Then, you could call validate in each form element's onchange event handler, using this to pass it the form element, as in the following example:
<input type="text" name="age" size="3" onChange="validate(this, 18, 99)">
In general, this refers to the calling object in a method.
When combined with the form property, this can refer to the
current object's parent form. In the following example, the form
myForm
contains a Text
object and a button. When the user clicks the
button, the value of the Text
object is
set to the form's name. The button's onclick event handler uses
this.form to refer to the parent form, myForm
.
<form name="myForm"> <p><label>Form name:<input type="text" name="text1" value="Beluga"></label> <p><input name="button1" type="button" value="Show Form Name" onclick="this.form.text1.value=this.form.name"> </p> </form>
A getter is a method that gets the value of a specific property. A setter is a method that sets the value of a specific property. You can define getters and setters on any predefined core object or user-defined object that supports the addition of new properties. The syntax for defining getters and setters uses the object literal syntax.
The following JS shell session illustrates how getters and setters could work for a user-defined object o. The JS shell is an application that allows developers to test JavaScript code in batch mode or interactively.
The o object's properties are:
o.a - a number
o.b - a getter that returns o.a plus 1
o.c - a setter that sets the value of o.a to half of its value
js> o = new Object; [object Object] js> o = {a:7, get b() {return this.a+1; }, set c(x) {this.a = x/2}}; [object Object] js> o.a 7 js> o.b 8 js> o.c = 50 js> o.a 25 js>
This JavaScript shell session illustrates how getters and
setters can extend the Date
prototype
to add a year property to all instances of the predefined
Date
class. It uses the Date
class's existing getFullYear
and setFullYear
methods to support the year property's
getter and setter.
These statements define a getter and setter for the year property:
js> var d = Date.prototype; js> d.__defineGetter__("year", function() { return this.getFullYear(); }); js> d.__defineSetter__("year", function(y) { this.setFullYear(y); });
These statements use the getter and setter in a Date object:
js> var now = new Date; js> print(now.year); 2000 js> now.year=2001; 987617605170 js> print(now); Wed Apr 18 11:13:25 GMT-0700 (Pacific Daylight Time) 2001
During development of JavaScript 1.5, there was a brief period in which expressions including getter = or setter = were used to define new getters or setters on existing objects. This syntax is highly deprecated now, will cause a warning in current JS 1.5 engines, and will become a syntax error in the future. It should be avoided.
In principle, getters and setters can be either
defined using Using Object Initializers, or
added later to any object at any time using a getter or setter adding method.
When defining getters and setters using Using Object Initializers all you need to do is to prefix a getter method with get and a setter method with set. Of course, the getter method must not expect a parameter, while the setter method expects exactly one parameter (the new value to set). For instance:
o = { a:7, get b() { return this.a+1; }, set c(x) { this.a = x/2; } };
Getters and setters can also be added to an object at any time
after creation using two special methods called __defineGetter__
and __defineSetter__
. Both methods expect the name of
the getter or setter as their first parameter, in form of a
string. The second parameter is the function to call as the
getter or setter. For instance (following the previous
example):
o.__defineGetter__("b", function() { return this.a+1; }); o.__defineSetter__("c", function(x) { this.a = x/2; });
Which of the two forms to choose depends on your programming style and task at hand. If you already go for the object initializer when defining a prototype you will probably most of the time choose the first form. This form is more compact and natural. However, if you need to add getters and setters later because you did not write the prototype or particular object then the second form is the only possible form. The second form probably best represents the dynamic nature of JavaScript but it can make the code hard to read and understand.
You can remove a property by using the delete operator. The following code shows how to remove a property.
//Creates a new object, myobj, with two properties, a and b. myobj = new Object; myobj.a = 5; myobj.b = 12; //Removes the a property, leaving myobj with only the b property. delete myobj.a;
You can also use delete to delete a global variable if the var keyword was not used to declare the variable:
g = 17; delete g;
See delete for more information.
This section describes the predefined objects in core JavaScript:
JavaScript does not have an explicit array data type. However,
you can use the predefined Array
object
and its methods to work with arrays in your applications. The
Array
object has methods for
manipulating arrays in various ways, such as joining, reversing,
and sorting them. It has a property for determining the array
length and other properties for use with regular expressions.
An array is an ordered
set of values that you refer to with a name and an index. For
example, you could have an array called emp
that contains employees' names indexed by their
employee number. So emp[1]
would be
employee number one, emp[2]
employee
number two, and so on.
To create an Array
object:
1. arrayObjectName = new Array(element0, element1, ..., elementN) 2. arrayObjectName = new Array(arrayLength)
arrayObjectName
is either the name
of a new object or a property of an existing object. When using
Array
properties and methods,
arrayObjectName
is either the name of
an existing Array object or a property of an existing
object.
element0, element1, ..., elementN is a list of values for the array's elements. When this form is specified, the array is initialized with the specified values as its elements, and the array's length property is set to the number of arguments.
arrayLength
is the initial length
of the array. The following code creates an array of five
elements:
billingMethod = new Array(5)
Array literals are also Array
objects; for example, the following literal is an Array
object. See Array Literals for
details on array literals.
coffees = ["French Roast", "Columbian", "Kona"]
You can populate an array by assigning values to its elements. For example,
emp[1] = "Casey Jones" emp[2] = "Phil Lesh" emp[3] = "August West"
You can also populate an array when you create it:
myArray = new Array("Hello", myVar, 3.14159)
You refer to an array's elements by using the element's ordinal number. For example, suppose you define the following array:
myArray = new Array("Wind","Rain","Fire")
You then refer to the first element of the array as
myArray[0]
and the second element of
the array as myArray[1]
.
The index of the elements begins with zero (0), but the
length of array (for example, myArray.length
) reflects the number of elements
in the array.
The Array
object has the following
methods:
concat joins two arrays and returns a new array.
myArray = new Array("1","2","3") myArray = myArray.concat("a", "b", "c"); // myArray is now ["1", "2", "3", "a", "b", "c"]
join(deliminator = ",") joins all elements of an array into a string.
myArray = new Array("Wind","Rain","Fire") list = myArray.join(" - "); // list is "Wind - Rain - Fire"
pop removes the last element from an array and returns that element.
myArray = new Array("1", "2", "3"); last=myArray.pop(); // MyArray is now ["1", "2"], last = "3"
push adds one or more elements to the end of an array and returns that last element added.
myArray = new Array("1", "2"); myArray.push("3"); // MyArray is now ["1", "2", "3"]
reverse transposes the elements of an array: the first array element becomes the last and the last becomes the first.
myArray = new Array ("1", "2", "3"); myArray.reverse(); // transposes the array so that myArray = [ "3", "2", "1" ]
shift removes the first element from an array and returns that element
myArray = new Array ("1", "2", "3"); first=myArray.shift(); // MyArray is now ["2", "3"], first is "1"
slice (start_index,
upto_index)
extracts a section of an array and
returns a new array.
myArray = new Array ("a", "b", "c", "d", "e"); myArray = myArray.slice(1,4); //starts at index 1 and extracts all elements until index 4, returning [ "b", "c", "d" ]
splice(index, count_to_remove,
addelement1, addelement2, ...)
adds and/or removes
elements from an array.
myArray = new Array ("1", "2", "3", "4", "5"); myArray.splice(1,3,"a","b","c", "d"); // MyArray is now ["1", "a", "b", "c", "d", "5"] // this code started at index one (or where the "2" was), removed 3 elements there, and then inserted all consecutive elements in its place
sort
sorts the elements of
an array.
myArray = new Array("Wind","Rain","Fire") myArray.sort(); // sorts the array so that myArrray = [ "Fire", "Rain", "Wind" ]
sort
can also take a callback
function to determine how array content is sorted. The function
compares two values and returns one of three values:
if a is less than b by the sorting system, return -1 (or any negative number)
if a is greater than b by the sorting system, return 1 (or any positive number)
if a and b is considered equivalent, return 0.
For, instance, the following will support by the last letter of an array:
var sortFn = function(a,b){ if (a[a.length - 1] < b[b.length - 1]) return -1; if (a[a.length - 1] > b[b.length - 1]) return 1; if (a[a.length - 1] == b[b.length - 1]) return 0; } myArray.sort(sortFn); // sorts the array so that myArray = ["Wind","Fire","Rain"]
unshift
adds one or more
elements to the front of an array and returns the new
length of the array.
The following code creates a two-dimensional array.
a = new Array(4) for (i=0; i < 4; i++) { a[i] = new Array(4) for (j=0; j < 4; j++) { a[i][j] = "["+i+","+j+"]" } }
This example creates an array with the following rows:
Row 0:[0,0][0,1][0,2][0,3] Row 1:[1,0][1,1][1,2][1,3] Row 2:[2,0][2,1][2,2][2,3] Row 3:[3,0][3,1][3,2][3,3]
When an array is the result of a match between a regular
expression and a string, the array returns properties and
elements that provide information about the match. An array is
the return value of RegExp.exec
,
String.match
, and String.split
. For information on using arrays
with regular expressions, see Chapter 4, Regular
Expressions.
The Boolean
object is a wrapper
around the primitive Boolean
data type.
Use the following syntax to create a Boolean
object:
booleanObjectName = new Boolean(value)
Do not confuse the primitive Boolean
values true
and false
with the true
and
false
values of the Boolean
object. Any object whose value is not
undefined
, null
, 0, NaN
, or the
empty string, including a Boolean
object whose value is false
, evaluates
to true
when passed to a conditional
statement. See if...else Statement for more
information.
JavaScript does not have a date data type. However, you can
use the Date
object and its methods to
work with dates and times in your applications. The Date
object has a large number of methods for
setting, getting, and manipulating dates. It does not have any
properties.
JavaScript handles dates similarly to Java. The two languages have many of the same date methods, and both languages store dates as the number of milliseconds since January 1, 1970, 00:00:00.
The Date object range is -100,000,000 days to 100,000,000 days relative to 01 January, 1970 UTC.
To create a Date object:
dateObjectName = new Date([parameters])
where dateObjectName
is the name of
the Date
object being created; it can
be a new object or a property of an existing object.
The parameters in the preceding syntax can be any of the following:
Nothing: creates today's date and time. For example,
today = new Date()
.
A string representing a date in the following form:
"Month day, year hours:minutes:seconds." For example,
Xmas95 = new Date("December 25, 1995
13:30:00")
. If you omit hours, minutes, or seconds,
the value will be set to zero.
A set of integer values for year, month, and day. For
example, Xmas95 = new
Date(1995,11,25)
.
A set of integer values for year, month, day, hour,
minute, and seconds. For example, Xmas95
= new Date(1995,11,25,9,30,0)
.
JavaScript 1.2 and
earlier The Date
object
behaves as follows:
Dates prior to 1970 are not allowed.
JavaScript depends on platform-specific date facilities
and behavior; the behavior of the Date
object varies from platform to
platform.
The Date
object methods for
handling dates and times fall into these broad categories:
"set" methods, for setting date and time values in
Date
objects.
"get" methods, for getting date and time values from
Date
objects.
"to" methods, for returning string values from
Date
objects.
parse and UTC methods, for parsing Date
strings.
With the get
and set
methods you can get and set seconds, minutes,
hours, day of the month, day of the week, months, and years
separately. There is a getDay
method
that returns the day of the week, but no corresponding
setDay
method, because the day of the
week is set automatically. These methods use integers to
represent these values as follows:
Seconds and minutes: 0 to 59
Hours: 0 to 23
Day: 0 (Sunday) to 6 (Saturday)
Date: 1 to 31 (day of the month)
Months: 0 (January) to 11 (December)
Year: years since 1900
For example, suppose you define the following date:
Xmas95 = new Date("December 25, 1995")
Then Xmas95.getMonth()
returns 11,
and Xmas95.getFullYear()
returns
1995.
The getTime
and setTime
methods are useful for comparing dates.
The getTime
method returns the number
of milliseconds since January 1, 1970, 00:00:00 for a
Date
object.
For example, the following code displays the number of days left in the current year:
today = new Date() endYear = new Date(1995,11,31,23,59,59,999) // Set day and month endYear.setFullYear(today.getFullYear()) // Set year to this year msPerDay = 24 * 60 * 60 * 1000 // Number of milliseconds per day daysLeft = (endYear.getTime() - today.getTime()) / msPerDay daysLeft = Math.round(daysLeft) //returns days left in the year
This example creates a Date
object
named today that contains today's date. It then creates a
Date
object named endYear
and sets the year to the current year.
Then, using the number of milliseconds per day, it computes the
number of days between today and endYear
, using getTime
and rounding to a whole number of days.
The parse method is useful for assigning values from date
strings to existing Date
objects. For
example, the following code uses parse and setTime
to assign a date value to the IPOdate
object:
IPOdate = new Date() IPOdate.setTime(Date.parse("Aug 9, 1995"))
In the following example, the function JSClock() returns the time in the format of a digital clock.
function JSClock() { var time = new Date() var hour = time.getHours() var minute = time.getMinutes() var second = time.getSeconds() var temp = "" + ((hour > 12) ? hour - 12 : hour) if (hour == 0) temp = "12"; temp += ((minute < 10) ? ":0" : ":") + minute temp += ((second < 10) ? ":0" : ":") + second temp += (hour >= 12) ? " P.M." : " A.M." return temp }
The JSClock
function first creates
a new Date
object called time; since
no arguments are given, time is created with the current date
and time. Then calls to the getHours
,
getMinutes
, and getSeconds
methods assign the value of the
current hour, minute and seconds to hour, minute, and
second.
The next four statements build a string value based on the time. The first statement creates a variable temp, assigning it a value using a conditional expression; if hour is greater than 12, (hour - 12), otherwise simply hour, unless hour is 0, in which case it becomes 12.
The next statement appends a minute value to temp. If the value of minute is less than 10, the conditional expression adds a string with a preceding zero; otherwise it adds a string with a demarcating colon. Then a statement appends a seconds value to temp in the same way.
Finally, a conditional expression appends "PM" to temp if hour is 12 or greater; otherwise, it appends "AM" to temp.
The predefined Function
object
specifies a string of JavaScript code to be compiled as a
function.
To create a Function
object:
functionObjectName = new Function ([arg1, arg2, ... argn], functionBody)
functionObjectName
is the name of a
variable or a property of an existing object. It can also be an
object followed by a lowercase event handler name, such as
window.onerror.
arg1, arg2, ... argn are arguments to be used by the function as formal argument names. Each must be a string that corresponds to a valid JavaScript identifier; for example "x" or "theForm".
functionBody
is a string specifying
the JavaScript code to be compiled as the function body.
Function objects are evaluated each time they are used. This is less efficient than declaring a function and calling it within your code, because declared functions are compiled.
The following code assigns a function to the variable
setBGColor
. This function sets the
current document's background color.
var setBGColor = new Function("document.bgColor='antiquewhite'")
To call the Function
object, you can
specify the variable name as if it were a function. The following
code executes the function specified by the setBGColor
variable:
var colorChoice="antiquewhite" if (colorChoice=="antiquewhite") {setBGColor()}
You can assign the function to an event handler in either of the following ways:
1. document.form1.colorButton.onclick=setBGColor 2. <input name="colorButton" type="button" VALUE="Change background color" onClick="setBGColor()">
Creating the variable setBGColor
shown above is similar to declaring the following function:
function setBGColor() { document.bgColor='antiquewhite' }
Assigning a function to a variable is similar to declaring a function, but there are differences:
When you assign a function to a variable using var
setBGColor = new Function("...")
,
setBGColor
is a variable for
which the current value is a reference to the function
created with new Function()
.
When you create a function using function setBGColor() {...}
, setBGColor
is not a variable, it is the name
of a function.
You can nest a function within a function. The nested (inner) function is private to its containing (outer) function:
The inner function can be accessed only from statements in the outer function.
The inner function can use the arguments and variables of the outer function. The outer function cannot use the arguments and variables of the inner function.
The predefined Math
object has
properties and methods for mathematical constants and functions.
For example, the Math
object's
PI
property has the value of pi
(3.141...), which you would use in an application as
Math.PI
Similarly, standard mathematical functions are methods of
Math
. These include trigonometric,
logarithmic, exponential, and other functions. For example, if
you want to use the trigonometric function sine, you would
write
Math.sin(1.56)
Note that all trigonometric methods of Math take arguments in radians.
The following table summarizes the Math object's methods.
Method | Description |
---|---|
abs | Absolute value |
sin , cos , tan |
Standard trigonometric functions; argument in radians |
acos , asin , atan ,
atan2 |
Inverse trigonometric functions; return values in radians |
exp , log |
Exponential and natural logarithm, base e |
ceil |
Returns least integer greater than or equal to argument |
floor |
Returns greatest integer less than or equal to argument |
min , max |
Returns greater or lesser (respectively) of two arguments |
pow |
Exponential; first argument is base, second is exponent |
random |
Returns a random number between 0 and 1. |
round |
Rounds argument to nearest integer |
sqrt |
Square root |
Table 7.1: Methods of Math
Unlike many other objects, you never create a Math
object of your own. You always use the
predefined Math
object.
The Number
object has properties for
numerical constants, such as maximum value, not-a-number, and
infinity. You cannot change the values of these properties and
you use them as follows:
biggestNum = Number.MAX_VALUE smallestNum = Number.MIN_VALUE infiniteNum = Number.POSITIVE_INFINITY negInfiniteNum = Number.NEGATIVE_INFINITY notANum = Number.NaN
You always refer to a property of the predefinedNumber
object as shown above, and not as a property
of aNumber
object you create
yourself.
The following table summarizes theNumber
object's properties.
Property | Description |
---|---|
MAX_VALUE | The largest representable number |
MIN_VALUE | The smallest representable number |
NaN | Special "not a number" value |
NEGATIVE_INFINITY | Special negative infinite value; returned on overflow |
POSITIVE_INFINITY | Special positive infinite value; returned on overflow |
Table 7.2: Properties of Number
The Number
prototype provides
methods for retrieving information from Number
objects in various formats. The following
table summarizes the methods of Number.prototype.
Method | Description |
---|---|
toExponential |
Returns a string representing the number in exponential notation. |
toFixed |
Returns a string representing the number in fixed-point notation. |
toPrecision |
Returns a string representing the number to a specified precision in fixed-point notation. |
toSource |
Returns an object literal representing the specified
Number object; you can use this
value to create a new object. Overrides the Object.toSource method. |
toString |
Returns a string representing the specified object.
Overrides the Object.toString
method. |
valueOf |
Returns the primitive value of the specified object.
Overrides the Object.valueOf
method. |
Table 7.3: Methods of Number.prototype
The RegExp
object lets you work with
regular expressions. It is described in Chapter 4, Regular
Expressions.
A String
object has one property,
length
, that indicates the number of
characters in the string. For example, the following code assigns
x
the value 13, because "Hello, World!"
has 13 characters:
myString = "Hello, World!" x = mystring.length
A String
object has two types of
methods: those that return a variation on the string itself, such
as substring and toUpperCase
, and those
that return an HTML-formatted version of the string, such as bold
and link.
For example, using the previous example, both mystring.toUpperCase()
and "hello, world!".toUpperCase()
return the string
"HELLO, WORLD!"
The substring method takes two arguments and returns a subset
of the string between the two arguments. Using the previous
example, mystring.substring(4, 9)
returns the string "o, Wo"
. See the
substring method of the String
object
in the Core JavaScript Reference for more
information.
The String
object also has a number
of methods for automatic HTML formatting, such as bold to create
boldface text and link to create a hyperlink. For example, you
could create a hyperlink to a hypothetical URL with the link
method as follows:
mystring.link("http://www.helloworld.com")
The following table summarizes the methods of String
objects.
Method | Description |
---|---|
Creates HTML named anchor. | |
Create HTML formatted string. | |
Return the character or character code at the specified position in string. | |
Return the position of specified substring in the string or last position of specified substring, respectively. | |
Creates HTML hyperlink. | |
Combines the text of two strings and returns a new string. | |
Constructs a string from the specified sequence of
Unicode values. This is a method of the String class, not a String instance. |
|
Splits a String object into
an array of strings by separating the string into
substrings. |
|
Extracts a section of an string and returns a new string. | |
Return the specified subset of the string, either by specifying the start and end indexes or the start index and a length. | |
Work with regular expressions. | |
Return the string in all lowercase or all uppercase, respectively. |
Table 7.4: Methods of String Instances
The String
object is a wrapper
around the string primitive data type. Do not confuse a string
literal with the String
object. For
example, the following code creates the string literal
s1
and also the String
object s2
:
s1 = "foo" //creates a string literal value s2 = new String("foo") //creates a String object
You can call any of the methods of the String
object on a string literal value -
JavaScript automatically converts the string literal to a
temporary String
object, calls the
method, then discards the temporary String
object. You can also use the String.length
property with a string literal.
You should use string literals unless you specifically need
to use a String
object, because
String
objects can have
counterintuitive behavior. For example:
s1 = "2 + 2" //creates a string literal value s2 = new String("2 + 2")//creates a String object eval(s1) //returns the number 4 eval(s2) //returns the string "2 + 2"
Class-based object-oriented languages, such as Java and C++, are founded on the concept of two distinct entities: classes and instances.
A class defines all of the properties (considering
methods and fields in Java, or members in C++, to be
properties) that characterize a certain set of objects. A
class is an abstract thing, rather than any particular
member of the set of objects it describes. For example, the
Employee
class could represent
the set of all employees.
An instance, on the other hand, is the instantiation of
a class; that is, one of its members. For example, Victoria
could be an instance of the Employee
class, representing a particular
individual as an employee. An instance has exactly the
properties of its parent class (no more, no less).
A prototype-based language, such as JavaScript, does not make this distinction: it simply has objects. A prototype-based language has the notion of a prototypical object, an object used as a template from which to get the initial properties for a new object. Any object can specify its own properties, either when you create it or at run time. In addition, any object can be associated as the prototype for another object, allowing the second object to share the first object's properties.
In class-based languages, you define a class in a separate class definition. In that definition you can specify special methods, called constructors, to create instances of the class. A constructor method can specify initial values for the instance's properties and perform other processing appropriate at creation time. You use the new operator in association with the constructor method to create class instances.
JavaScript follows a similar model, but does not have a class definition separate from the constructor. Instead, you define a constructor function to create objects with a particular initial set of properties and values. Any JavaScript function can be used as a constructor. You use the new operator with a constructor function to create a new object.
In a class-based language, you create a hierarchy of classes
through the class definitions. In a class definition, you can
specify that the new class is a subclass of an already existing
class. The subclass inherits all the properties of the
superclass and additionally can add new properties or modify
the inherited ones. For example, assume the Employee
class includes only the name and dept
properties, and Manager
is a subclass
of Employee
that adds the reports
property. In this case, an instance of the Manager
class would have all three properties:
name, dept, and reports.
JavaScript implements inheritance by allowing you to
associate a prototypical object with any constructor function.
So, you can create exactly the Employee-Manager example, but
you use slightly different terminology. First you define the
Employee
constructor function,
specifying the name and dept properties. Next, you define the
Manager
constructor function,
specifying the reports property. Finally, you assign a new
Employee
object as the prototype for
the Manager
constructor function.
Then, when you create a new Manager
,
it inherits the name and dept properties from the Employee
object.
In class-based languages, you typically create a class at compile time and then you instantiate instances of the class either at compile time or at run time. You cannot change the number or the type of properties of a class after you define the class. In JavaScript, however, at run time you can add or remove properties of any object. If you add a property to an object that is used as the prototype for a set of objects, the objects for which it is the prototype also get the new property.
The following table gives a short summary of some of these differences. The rest of this chapter describes the details of using JavaScript constructors and prototypes to create an object hierarchy and compares this to how you would do it in Java.
Class-based (Java) | Prototype-based (JavaScript) |
---|---|
Class and instance are distinct entities. | All objects are instances. |
Define a class with a class definition; instantiate a class with constructor methods. | Define and create a set of objects with constructor functions. |
Create a single object with the new operator. | Same. |
Construct an object hierarchy by using class definitions to define subclasses of existing classes. | Construct an object hierarchy by assigning an object as the prototype associated with a constructor function. |
Inherit properties by following the class chain. | Inherit properties by following the prototype chain. |
Class definition specifies all properties of all instances of a class. Cannot add properties dynamically at run time. | Constructor function or prototype specifies an initial set of properties. Can add or remove properties dynamically to individual objects or to the entire set of objects. |
The remainder of this chapter uses the employee hierarchy shown in the following figure.
Figure 8.1: A simple object hierarchy
This example uses the following objects:
Employee
has the properties
name (whose value defaults to the empty string) and dept
(whose value defaults to "general").
Manager is based on Employee
.
It adds the reports property (whose value defaults to an
empty array, intended to have an array of Employee
objects as its value).
WorkerBee
is also based on
Employee
. It adds the projects
property (whose value defaults to an empty array, intended
to have an array of strings as its value).
SalesPerson is based on WorkerBee
. It adds the quota property (whose
value defaults to 100). It also overrides the dept property
with the value "sales", indicating that all salespersons
are in the same department.
Engineer
is based on
WorkerBee
. It adds the machine
property (whose value defaults to the empty string) and
also overrides the dept property with the value
"engineering".
The rest of the example:
There are several ways to define appropriate constructor
functions to implement the Employee
hierarchy. How you choose to define them depends largely on
what you want to be able to do in your application.
This section shows how to use very simple (and comparatively inflexible) definitions to demonstrate how to get the inheritance to work. In these definitions, you cannot specify any property values when you create an object. The newly-created object simply gets the default values, which you can change at a later time. Figure 8.2 illustrates the hierarchy with these simple definitions.
In a real application, you would probably define constructors that allow you to provide property values at object creation time (see More Flexible Constructors for information). For now, these simple definitions demonstrate how the inheritance occurs.
Figure 8.2: The Employee object definitions
The following Java and JavaScript Employee
definitions are similar. The only
differences are that you need to specify the type for each
property in Java but not in JavaScript, and you need to create
an explicit constructor method for the Java class.
JavaScript | Java |
---|---|
function Employee () { this.name = ""; this.dept = "general"; } |
public class Employee { public String name; public String dept; public Employee () { this.name = ""; this.dept = "general"; } } |
The Manager
and WorkerBee
definitions show the difference in how
to specify the next object higher in the inheritance chain. In
JavaScript, you add a prototypical instance as the value of the
prototype property of the constructor function. You can do so
at any time after you define the constructor. In Java, you
specify the superclass within the class definition. You cannot
change the superclass outside the class definition.
JavaScript | Java |
---|---|
function Manager () { this.reports = []; } Manager.prototype = new Employee; function WorkerBee () { this.projects = []; } WorkerBee.prototype = new Employee; |
public class Manager extends Employee { public Employee[] reports; public Manager () { this.reports = new Employee[0]; } } public class WorkerBee extends Employee { public String[] projects; public WorkerBee () { this.projects = new String[0]; } } |
The Engineer
and SalesPerson
definitions create objects that
descend from WorkerBee
and hence from
Employee
. An object of these types
has properties of all the objects above it in the chain. In
addition, these definitions override the inherited value of the
dept property with new values specific to these objects.
JavaScript | Java |
---|---|
function SalesPerson () { this.dept = "sales"; this.quota = 100; } SalesPerson.prototype = new WorkerBee; function Engineer () { this.dept = "engineering"; this.machine = ""; } Engineer.prototype = new WorkerBee; |
public class SalesPerson extends WorkerBee { public double quota; public SalesPerson () { this.dept = "sales"; this.quota = 100.0; } } public class Engineer extends WorkerBee { public String machine; public Engineer () { this.dept = "engineering"; this.machine = ""; } } |
Using these definitions, you can create instances of these objects that get the default values for their properties. Figure 8.3 illustrates using these JavaScript definitions to create new objects and shows the property values for the new objects.
Note: The term
instance has a specific
technical meaning in class-based languages. In these languages,
an instance is an individual member of a class and is
fundamentally different from a class. In JavaScript, "instance"
does not have this technical meaning because JavaScript does
not have this difference between classes and instances.
However, in talking about JavaScript, "instance" can be used
informally to mean an object created using a particular
constructor function. So, in this example, you could informally
say that jane is an instance of Engineer
. Similarly, although the terms
parent, child, ancestor,
and descendant do not
have formal meanings in JavaScript; you can use them informally
to refer to objects higher or lower in the prototype chain.
Figure 8.3: Creating objects with simple definitions
This section discusses how objects inherit properties from other objects in the prototype chain and what happens when you add a property at run time.
Suppose you create the mark object as a WorkerBee
(as shown in Creating the Hierarchy) with the
following statement:
mark = new WorkerBee;
When JavaScript sees the new operator, it creates a new
generic object and passes this new object as the value of the
this keyword to the WorkerBee
constructor function. The constructor function explicitly
sets the value of the projects property, and implicitly sets
the value of the internal __proto__
property to the value of WorkerBee.prototype
. (That property name has
two underscore characters at the front and two at the end.)
The __proto__
property determines
the prototype chain used to return property values. Once
these properties are set, JavaScript returns the new object
and the assignment statement sets the variable mark to that
object.
This process does not explicitly put values in the mark
object (local values)
for the properties that mark inherits from the prototype
chain. When you ask for the value of a property, JavaScript
first checks to see if the value exists in that object. If it
does, that value is returned. If the value is not there
locally, JavaScript checks the prototype chain (using the
__proto__
property). If an object
in the prototype chain has a value for the property, that
value is returned. If no such property is found, JavaScript
says the object does not have the property. In this way, the
mark object has the following properties and values:
mark.name = ""; mark.dept = "general"; mark.projects = [];
The mark object inherits values for the name and dept
properties from the prototypical object in mark.__proto__
. It is assigned a local value
for the projects property by the WorkerBee
constructor. This gives you
inheritance of properties and their values in JavaScript.
Some subtleties of this process are discussed in Property Inheritance
Revisited.
Because these constructors do not let you supply
instance-specific values, this information is generic. The
property values are the default ones shared by all new
objects created from WorkerBee
. You
can, of course, change the values of any of these properties.
So, you could give specific information for mark as
follows:
mark.name = "Doe, Mark"; mark.dept = "admin"; mark.projects = ["navigator"];
In JavaScript, you can add properties to any object at run time. You are not constrained to use only the properties provided by the constructor function. To add a property that is specific to a single object, you assign a value to the object, as follows:
mark.bonus = 3000;
Now, the mark object has a bonus property, but no other
WorkerBee
has this property.
If you add a new property to an object that is being used as the prototype for a constructor function, you add that property to all objects that inherit properties from the prototype. For example, you can add a specialty property to all employees with the following statement:
Employee.prototype.specialty = "none";
As soon as JavaScript executes this statement, the mark
object also has the specialty property with the value of
"none". The following figure shows the effect of adding this
property to the Employee
prototype
and then overriding it for the Engineer
prototype.
Figure 8.4: Adding properties
The constructor functions shown so far do not let you specify property values when you create an instance. As with Java, you can provide arguments to constructors to initialize property values for instances. The following figure shows one way to do this.
Figure 8.5: Specifying properties in a constructor, take 1
The following table shows the Java and JavaScript definitions for these objects.
JavaScript | Java |
---|---|
function Employee (name, dept) { this.name = name || ""; this.dept = dept || "general"; } |
public class Employee { public String name; public String dept; public Employee () { this("", "general"); } public Employee (String name) { this(name, "general"); } public Employee (String name, String dept) { this.name = name; this.dept = dept; } } |
function WorkerBee (projs) { this.projects = projs || []; } WorkerBee.prototype = new Employee; |
public class WorkerBee extends Employee { public String[] projects; public WorkerBee () { this(new String[0]); } public WorkerBee (String[] projs) { this.projects = projs; } } |
function Engineer (mach) { this.dept = "engineering"; this.machine = mach || ""; } Engineer.prototype = new WorkerBee; |
public class Engineer extends WorkerBee { public String machine; public WorkerBee () { this.dept = "engineering"; this.machine = ""; } public WorkerBee (String mach) { this.dept = "engineering"; this.machine = mach; } } |
These JavaScript definitions use a special idiom for setting default values:
this.name = name || "";
The JavaScript logical OR
operator
(||) evaluates its first argument. If that argument converts to
true
, the operator returns it.
Otherwise, the operator returns the value of the second
argument. Therefore, this line of code tests to see if name has
a useful value for the name property. If it does, it sets
this.name to that value. Otherwise, it sets this.name
to the empty string. This chapter uses
this idiom for brevity; however, it can be puzzling at first
glance. Please note:
This may not work as expected with numeric or boolean
arguments, as both 0 (zero) and false
will cause the default value to be chosen; in this case you
will need to use the following more cumbersome idiom, which
gives the desired behaviour with all data types:
this.authorized = typeof(authorized) !== 'undefined' ? authorized : true;
With these definitions, when you create an instance of an
object, you can specify values for the locally defined
properties. As shown in Figure 8.5, you can use the following
statement to create a new Engineer
:
jane = new Engineer("belau");
Jane's properties are now:
jane.name == ""; jane.dept == "engineering"; jane.projects == []; jane.machine == "belau"
Notice that with these definitions, you cannot specify an initial value for an inherited property such as name. If you want to specify an initial value for inherited properties in JavaScript, you need to add more code to the constructor function.
So far, the constructor function has created a generic object and then specified local properties and values for the new object. You can have the constructor add more properties by directly calling the constructor function for an object higher in the prototype chain. The following figure shows these new definitions.
Figure 8.6 Specifying properties in a constructor, take 2
Let's look at one of these definitions in detail. Here's the
new definition for the Engineer
constructor:
function Engineer (name, projs, mach) { this.base = WorkerBee; this.base(name, "engineering", projs); this.machine = mach || ""; }
Suppose you create a new Engineer
object as follows:
jane = new Engineer("Doe, Jane", ["navigator", "javascript"], "belau");
JavaScript follows these steps:
The new operator creates a generic object and sets its
__proto__
property to
Engineer.prototype
.
The new operator passes the new object to the
Engineer
constructor as the
value of the this keyword.
The constructor creates a new property called base for
that object and assigns the value of the WorkerBee
constructor to the base property.
This makes the WorkerBee
constructor a method of the Engineer
object.
The name of the base property is not special. You can use any legal property name; base is simply evocative of its purpose.
The constructor calls the base method, passing as its
arguments two of the arguments passed to the constructor
("Doe, Jane" and ["navigator", "javascript"]) and also
the string "engineering". Explicitly using "engineering"
in the constructor indicates that all Engineer
objects have the same value for
the inherited dept property, and this value overrides the
value inherited from Employee
.
Because base is a method of Engineer, within the call
to base, JavaScript binds the this keyword to the object
created in Step 1. Thus, the WorkerBee
function in turn passes the "Doe,
Jane" and ["navigator", "javascript"] arguments to the
Employee
constructor function.
Upon return from the Employee
constructor function, the WorkerBee
function uses the remaining
argument to set the projects property.
Upon return from the base method, the Engineer
constructor initializes the
object's machine
property to
"belau".
Upon return from the constructor, JavaScript assigns
the new object to the jane
variable.
You might think that, having called the WorkerBee
constructor from inside the
Engineer
constructor, you have set up
inheritance appropriately for Engineer
objects. This is not the case. Calling
the WorkerBee
constructor ensures
that an Engineer
object starts out
with the properties specified in all constructor functions that
are called. However, if you later add properties to the
Employee
or WorkerBee
prototypes, those properties are not
inherited by the Engineer
object. For
example, assume you have the following statements:
function Engineer (name, projs, mach) { this.base = WorkerBee; this.base(name, "engineering", projs); this.machine = mach || ""; } jane = new Engineer("Doe, Jane", ["navigator", "javascript"], "belau"); Employee.prototype.specialty = "none";
The jane object does not inherit the specialty property. You still need to explicitly set up the prototype to ensure dynamic inheritance. Assume instead you have these statements:
function Engineer (name, projs, mach) { this.base = WorkerBee; this.base(name, "engineering", projs); this.machine = mach || ""; } Engineer.prototype = new WorkerBee; jane = new Engineer("Doe, Jane", ["navigator", "javascript"], "belau"); Employee.prototype.specialty = "none";
Now the value of the jane object's specialty property is "none".
Another way of inheriting is by using the .call/.apply methods. Below are equivalent:
function Engineer (name, projs, mach) { this.base = WorkerBee; this.base(name, "engineering", projs); this.machine = mach || ""; } function Engineer (name, projs, mach) { WorkerBee.call(this, name, "engineering", projs); this.machine = mach || ""; }
Using the javascript .call
method
makes a cleaner implementation because the .base
is not needed anymore.
The preceding sections described how JavaScript constructors and prototypes provide hierarchies and inheritance. This section discusses some subtleties that were not necessarily apparent in the earlier discussions.
When you access an object property, JavaScript performs these steps, as described earlier in this chapter:
Check to see if the value exists locally. If it does, return that value.
If there is not a local value, check the prototype
chain (using the __proto__
property).
If an object in the prototype chain has a value for the specified property, return that value.
If no such property is found, the object does not have the property.
The outcome of these steps depends on how you define things along the way. The original example had these definitions:
function Employee () { this.name = ""; this.dept = "general"; } function WorkerBee () { this.projects = []; } WorkerBee.prototype = new Employee;
With these definitions, suppose you create amy as an
instance of WorkerBee
with the
following statement:
amy = new WorkerBee;
The amy object has one local property, projects. The
values for the name and dept properties are not local to amy
and so are gotten from the amy object's __proto__
property. Thus, amy has these
property values:
amy.name == ""; amy.dept == "general"; amy.projects == [];
Now suppose you change the value of the name property in
the prototype associated with Employee
:
Employee.prototype.name = "Unknown"
At first glance, you might expect that new value to
propagate down to all the instances of Employee
. However, it does not.
When you create any
instance of the Employee
object,
that instance gets a local value for the name property (the
empty string). This means that when you set the WorkerBee
prototype by creating a new
Employee
object, WorkerBee.prototype
has a local value for the
name property. Therefore, when JavaScript looks up the name
property of the amy object (an instance of WorkerBee
), JavaScript finds the local value
for that property in WorkerBee.prototyWorkerBeepe
. It therefore does
not look farther up the chain to Employee.prototype
.
If you want to change the value of an object property at run time and have the new value be inherited by all descendants of the object, you cannot define the property in the object's constructor function. Instead, you add it to the constructor's associated prototype. For example, assume you change the preceding code to the following:
function Employee () { this.dept = "general"; } Employee.prototype.name = ""; function WorkerBee () { this.projects = []; } WorkerBee.prototype = new Employee; amy = new WorkerBee; Employee.prototype.name = "Unknown";
In this case, the name property of amy becomes "Unknown".
As these examples show, if you want to have default values for object properties and you want to be able to change the default values at run time, you should set the properties in the constructor's prototype, not in the constructor function itself.
You may want to know what objects are in the prototype chain for an object, so that you can tell from what objects this object inherits properties.
Starting with JavaScript 1.4, JavaScript provides an instanceof operator to test the prototype chain. This operator works exactly like the instanceof function discussed below.
As discussed in Inheriting Properties, when you
use the new operator with a constructor function to create a
new object, JavaScript sets the __proto__
property of the new object to the
value of the prototype property of the constructor function.
You can use this to test the prototype chain.
For example, suppose you have the same set of definitions
already shown, with the prototypes set appropriately. Create
a __proto__
object as follows:
chris = new Engineer("Pigman, Chris", ["jsd"], "fiji");
With this object, the following statements are all
true
:
chris.__proto__ == Engineer.prototype; chris.__proto__.__proto__ == WorkerBee.prototype; chris.__proto__.__proto__.__proto__ == Employee.prototype; chris.__proto__.__proto__.__proto__.__proto__ == Object.prototype; chris.__proto__.__proto__.__proto__.__proto__.__proto__ == null;
Given this, you could write an instanceOf function as follows:
function instanceOf(object, constructor) { while (object != null) { if (object == constructor.prototype) return true; object = object.__proto__; } return false; }
With this definition, the following expressions are all
true
:
instanceOf (chris, Engineer) instanceOf (chris, WorkerBee) instanceOf (chris, Employee) instanceOf (chris, Object)
But the following expression is false
:
instanceOf (chris, SalesPerson)
When you create constructors, you need to be careful if
you set global information in the constructor. For example,
assume that you want a unique ID to be automatically assigned
to each new employee. You could use the following definition
for Employee
:
var idCounter = 1; function Employee (name, dept) { this.name = name || ""; this.dept = dept || "general"; this.id = idCounter++; }
With this definition, when you create a new Employee
, the constructor assigns it the next
ID in sequence and then increments the global ID counter. So,
if your next statement is the following, victoria.id is 1 and
harry.id is 2:
victoria = new Employee("Pigbert, Victoria", "pubs") harry = new Employee("Tschopik, Harry", "sales")
At first glance that seems fine. However, idCounter gets
incremented every time an Employee
object is created, for whatever purpose. If you create the
entire Employee
hierarchy shown in
this chapter, the Employee
constructor is called every time you set up a prototype.
Suppose you have the following code:
var idCounter = 1; function Employee (name, dept) { this.name = name || ""; this.dept = dept || "general"; this.id = idCounter++; } function Manager (name, dept, reports) {...} Manager.prototype = new Employee; function WorkerBee (name, dept, projs) {...} WorkerBee.prototype = new Employee; function Engineer (name, projs, mach) {...} Engineer.prototype = new WorkerBee; function SalesPerson (name, projs, quota) {...} SalesPerson.prototype = new WorkerBee; mac = new Engineer("Wood, Mac");
Further assume that the definitions omitted here have the base property and call the constructor above them in the prototype chain. In this case, by the time the mac object is created, mac.id is 5.
Depending on the application, it may or may not matter that the counter has been incremented these extra times. If you care about the exact value of this counter, one possible solution involves instead using the following constructor:
function Employee (name, dept) { this.name = name || ""; this.dept = dept || "general"; if (name) this.id = idCounter++; }
When you create an instance of Employee
to use as a prototype, you do not
supply arguments to the constructor. Using this definition of
the constructor, when you do not supply arguments, the
constructor does not assign a value to the id and does not
update the counter. Therefore, for an Employee
to get an assigned id, you must
specify a name for the employee. In this example, mac.id
would be 1.
Some object-oriented languages allow multiple inheritance. That is, an object can inherit the properties and values from unrelated parent objects. JavaScript does not support multiple inheritance.
Inheritance of property values occurs at run time by JavaScript searching the prototype chain of an object to find a value. Because an object has a single associated prototype, JavaScript cannot dynamically inherit from more than one prototype chain.
In JavaScript, you can have a constructor function call more than one other constructor function within it. This gives the illusion of multiple inheritance. For example, consider the following statements:
function Hobbyist (hobby) { this.hobby = hobby || "scuba"; } function Engineer (name, projs, mach, hobby) { this.base1 = WorkerBee; this.base1(name, "engineering", projs); this.base2 = Hobbyist; this.base2(hobby); this.machine = mach || ""; } Engineer.prototype = new WorkerBee; dennis = new Engineer("Doe, Dennis", ["collabra"], "hugo")
Further assume that the definition of WorkerBee
is as used earlier in this chapter.
In this case, the dennis object has these properties:
dennis.name == "Doe, Dennis" dennis.dept == "engineering" dennis.projects == ["collabra"] dennis.machine == "hugo" dennis.hobby == "scuba"
So dennis does get the hobby property from the
Hobbyist
constructor. However,
assume you then add a property to the Hobbyist
constructor's prototype:
Hobbyist.prototype.equipment = ["mask", "fins", "regulator", "bcd"]
The dennis object does not inherit this new property.