Cover | Table of Contents | Colophon
<html><body><pre><script src="program.js"> </script></pre></body></html>
document.writeln('Hello, world!');
method method
is used to define new methods. This is its definition:Function.prototype.method = function (name, func) {
this.prototype[name] = func;
return this;
};
var that = this;
var and
that cannot be removed, but the other
spaces can be removed./* */ and line-ending comments
starting with //. Comments should be
used liberally to improve the readability of your programs. Take care
that the comments always accurately describe the code. Obsolete comments
are worse than no comments./* */ form of block
comments came from a language called PL/I. PL/I chose those strange
pairs as the symbols for comments because they were unlikely to occur in
that language's programs, except perhaps in string literals. In
JavaScript, those pairs can also occur in regular expression literals,
so block comments are not safe for commenting out blocks of code. For
example:
var that = this;
var and
that cannot be removed, but the other
spaces can be removed./* */ and line-ending comments
starting with //. Comments should be
used liberally to improve the readability of your programs. Take care
that the comments always accurately describe the code. Obsolete comments
are worse than no comments./* */ form of block
comments came from a language called PL/I. PL/I chose those strange
pairs as the symbols for comments because they were unlikely to occur in
that language's programs, except perhaps in string literals. In
JavaScript, those pairs can also occur in regular expression literals,
so block comments are not safe for commenting out blocks of code. For
example:/*
var rm_a = /a*/.match(s);
*/
/* */ comments be avoided and // comments be used instead. In this book,
// will be used exclusively.abstract boolean break byte case catch char class const continue debugger default delete do double else enum export extends false final finally float for function goto if implements import in instanceof int interface long native new null package private protected public return short static super switch synchronized this throw throws transient true try typeof var volatile void while with
undefined, NaN, and Infinity. It is not permitted to name a
variable or parameter with a reserved word. Worse, it is not permitted
to use a reserved word as the name of an object property in an object
literal or following a dot in a refinement.
double. Unlike most other programming
languages, there is no separate integer type, so 1 and 1.0
are the same value. This is a significant convenience because problems
of overflow in short integers are completely avoided, and all you need
to know about a number is that it is a number. A large class of numeric
type errors is avoided.
e by 10
raised to the power of the part after the e. So 100
and 1e2 are the same
number.- prefix operator.NaN is a number value
that is the result of an operation that cannot produce a normal result.
NaN is not equal to any value,
including itself. You can detect NaN
with the isNaN(
number )
function.Infinity represents
all values greater than 1.79769313486231570e+308.Math object that contains a set
of methods that act on numbers. For example, the Math.floor( number
) method can be used to convert a
number into an integer.
\ (backslash) is the escape character.
JavaScript was built at a time when Unicode was a 16-bit character set,
so all characters in JavaScript are 16 bits wide.
\u convention
allows for specifying character code points numerically."A" === "\u0041"
length property.
For example, "seven".length is
5.+ operator.
Two strings containing exactly the same characters in the same order are
considered to be the same string. So:'c' + 'a' + 't' === 'cat'
'cat'.toUpperCase( ) === 'CAT'
<script> tag
delivers a compilation unit that is compiled and immediately executed.
Lacking a linker, JavaScript throws them all together in a common global
namespace. There is more on global variables in .var statement defines the function's private
variables.
switch, while, for,
and do statements are allowed to have
an optional label prefix that interacts with
the break statement.
if and switch), by the looping statements (while, for,
and do), by the disruptive statements
(break, return, and throw), and by function invocation.
if statement changes the
flow of the program based on the value of the expression. The then block is executed if the expression is
truthy; otherwise, the optional
else branch is taken.falsenullundefined ''0NaNtrue, the string
true, false, null, undefined, NaN, or Infinity), an invocation expression preceded
by new, a refinement expression
preceded by delete, an expression
wrapped in parentheses, an expression preceded by a prefix operator, or
an expression followed by:? ternary operator
followed by another expression, then by :, and then by yet another
expression? ternary operator takes
three operands. If the first operand is truthy, it produces the value of
the second operand. But if the first operand is falsy, it produces the
value of the third operand.2 + 3 * 5 === 17 (2 + 3) * 5 === 25
. [] ( ) | Refinement and
invocation |
delete new typeof + - !
| Unary
operators |
* / % | Multiplication, division,
modulo |
+ - | Addition/concatenation,
subtraction |
>= <= > < | Inequality |
=== !== | Equality |
&& | Logical
and |
|| | Logical or |
?: | Ternary |
typeof
are 'number', 'string', 'boolean', 'undefined', 'function', and 'object'. If the operand is an array or
null, then the result is 'object', which is wrong. There will be more
about
true and false), null,
and undefined. All other values are
objects. Numbers, strings, and booleans are
object-like in that they have methods, but they are immutable. Objects in
JavaScript are mutable keyed collections. In JavaScript, arrays are
objects, functions are objects, regular expressions are objects, and, of
course, objects are objects.undefined.var empty_object = {};
var stooge = {
"first-name": "Jerome",
"last-name": "Howard"
};
"first-name", but are optional around first_name. Commas are used to separate the
pairs.var empty_object = {};
var stooge = {
"first-name": "Jerome",
"last-name": "Howard"
};
"first-name", but are optional around first_name. Commas are used to separate the
pairs.var flight = {
airline: "Oceanic",
number: 815,
departure: {
IATA: "SYD",
time: "2004-09-22 14:55",
city: "Sydney"
},
arrival: {
IATA: "LAX",
time: "2004-09-23 10:42",
city: "Los Angeles"
}
};
[ ] suffix. If the
string expression is a constant, and if it is a legal JavaScript name
and not a reserved word, then the .
notation can be used instead. The .
notation is preferred because it is more compact and it reads
better:stooge["first-name"] // "Joe" flight.departure.IATA // "SYD"
undefined value is produced
if an attempt is made to retrieve a nonexistent member:stooge["middle-name"] // undefined flight.status // undefined stooge["FIRST-NAME"] // undefined
|| operator can be used to
fill in default values:var middle = stooge["middle-name"] || "(none)"; var status = flight.status || "unknown";
undefined will throw a TypeError exception. This can be guarded
against with the &&
operator:flight.equipment // undefined flight.equipment.model // throw "TypeError" flight.equipment && flight.equipment.model // undefined
stooge['first-name'] = 'Jerome';
stooge['middle-name'] = 'Lester';
stooge.nickname = 'Curly';
flight.equipment = {
model: 'Boeing 777'
};
flight.status = 'overdue';
var x = stooge;
x.nickname = 'Curly';
var nick = stooge.nickname;
// nick is 'Curly' because x and stooge
// are references to the same object
var a = {}, b = {}, c = {};
// a, b, and c each refer to a
// different empty object
a = b = c = {};
// a, b, and c all refer to
// the same empty object
Object.prototype, an object that
comes standard with JavaScript.create method to the Object function. The beget method creates a new object that uses an
old object as its prototype. There will be much more about functions in
the next chapter.if (typeof Object.create !== 'function') {
Object.create = function (o) {
var F = function () {};
F.prototype = o;
return new F();
};
}
var another_stooge = Object.create(stooge);
another_stooge['first-name'] = 'Harry'; another_stooge['middle-name'] = 'Moses'; another_stooge.nickname = 'Moe';
Object.prototype. If the desired property
exists nowhere in the prototype chain, then the result is the undefined value. This is called
delegation.stooge.profession = 'actor'; another_stooge.profession // 'actor'
typeof operator can be
very helpful in determining the type of a property:typeof flight.number // 'number' typeof flight.status // 'string' typeof flight.arrival // 'object' typeof flight.manifest // 'undefined'
typeof flight.toString // 'function' typeof flight.constructor // 'function'
hasOwnProperty method, which returns true if the object has a particular property.
The hasOwnProperty method does not
look at the prototype chain:flight.hasOwnProperty('number') // true
flight.hasOwnProperty('constructor') // false
for in statement can loop
over all of the property names in an object. The enumeration will
include all of the properties—including functions and prototype
properties that you might not be interested in—so it is necessary to
filter out the values you don't want. The most common filters are the
hasOwnProperty method and using
typeof to exclude
functions:var name;
for (name in another_stooge) {
if (typeof another_stooge[name] !== 'function') {
document.writeln(name + ': ' + another_stooge[name]);
}
}
for in statement entirely and instead
make an array containing the names of the properties in the correct
order:var i;
var properties = [
'first-name',
'middle-name',
'last-name',
'profession'
];
for (i = 0; i < properties.length; i += 1) {
document.writeln(properties[i] + ': ' +
another_stooge[properties[i]]);
}
for instead of
for in, we were able to get the
properties we wanted without worrying about what might be dredged up
from the prototype chain, and we got them in the correct order.delete operator can be used
to remove a property from an object. It will remove a property from the
object if it has one. It will not touch any of the objects in the
prototype linkage.another_stooge.nickname // 'Moe' // Remove nickname from another_stooge, revealing // the nickname of the prototype. delete another_stooge.nickname; another_stooge.nickname // 'Curly'
var MYAPP = {};
MYAPP.stooge = {
"first-name": "Joe",
"last-name": "Howard"
};
MYAPP.flight = {
airline: "Oceanic",
number: 815,
departure: {
IATA: "SYD",
time: "2004-09-22 14:55",
city: "Sydney"
},
arrival: {
IATA: "LAX",
time: "2004-09-23 10:42",
city: "Los Angeles"
}
};
MYAPP.stooge refers to a top-level structure.
In the next chapter, we will see ways to use closure for information
hiding, which is another effective global abatement technique.Object.prototype. Function objects are linked
to Function.prototype (which is
itself linked to Object.prototype).
Every function is also created with two additional hidden properties:
the function's context and the code that implements the function's
behavior.prototype property. Its value is an object
with a constructor property whose
value is the function. This is distinct from the hidden link to Function.prototype. The meaning of this
convoluted construction will be revealed in the next chapter.// Create a variable called add and store a function // in it that adds two numbers. var add =
Object.prototype. Function objects are linked
to Function.prototype (which is
itself linked to Object.prototype).
Every function is also created with two additional hidden properties:
the function's context and the code that implements the function's
behavior.prototype property. Its value is an object
with a constructor property whose
value is the function. This is distinct from the hidden link to Function.prototype. The meaning of this
convoluted construction will be revealed in the next chapter.// Create a variable called add and store a function // in it that adds two numbers. var add = function (a, b) { return a + b; };
function.undefined, they will
be initialized to the arguments supplied when the function is
invoked.this and
arguments. The this parameter is very important in object
oriented programming, and its value is determined by the
invocation pattern. There are four patterns of
invocation in JavaScript: the method invocation pattern, the function
invocation pattern, the constructor invocation pattern, and the apply
invocation pattern. The patterns differ in how the bonus parameter
this is initialized.undefined value will be substituted for the
missing values. There is no type checking on the argument values: any
type of value can be passed to any parameter.this is bound to that object. If an
invocation expression contains a refinement (that is, a . dot expression or [subscript] expression), it is invoked as a
method:// Create myObject. It has a value and an increment
// method. The increment method takes an optional
// parameter. If the argument is not a number, then 1
// is used as the default.
var myObject = {
value: 0,
increment: function (inc) {
this.value += typeof inc === 'number' ? inc : 1;
}
};
myObject.increment( );
document.writeln(myObject.value); // 1
myObject.increment(2);
document.writeln(myObject.value); // 3arguments array. It
gives the function access to all of the arguments that were supplied
with the invocation, including excess arguments that were not assigned
to parameters. This makes it possible to write functions that take an
unspecified number of parameters:// Make a function that adds a lot of stuff.
// Note that defining the variable sum inside of
// the function does not interfere with the sum
// defined outside of the function. The function
// only sees the inner one.
var sum = function ( ) {
var i, sum = 0;
for (i = 0; i < arguments.length; i += 1) {
sum += arguments[i];
}
return sum;
};
document.writeln(sum(4, 8, 15, 16, 23, 42)); // 108
arguments is not really an array. It is an
array-like object. arguments has a
length property, but it lacks all of
the array methods. We will see a consequence of that design error at the
end of this chapter.} that closes the function body. That causes
the function to return control to the part of the program that invoked
the function.return statement can be
used to cause the function to return early. When return is executed, the function returns
immediately without executing the remaining statements.return value is not specified, then undefined is returned.new prefix and the return value is not an object, then this (the new object) is returned
instead.var add = function (a, b) {
if (typeof a !== 'number' || typeof b !== 'number') {
throw {
name: 'TypeError',
message: 'add needs numbers'
};
}
return a + b;
}
throw statement interrupts
execution of the function. It should be given an exception object containing a name property that identifies the type of the
exception, and a descriptive message
property. You can also add other properties.exception object will be
delivered to the catch clause of a
try statement:// Make a try_it function that calls the new add
// function incorrectly.
var try_it = function ( ) {
try {
add("seven");
} catch (e) {
document.writeln(e.name + ': ' + e.message);
}
}
try_it( );
try block, control will go to its catch clause.try statement has a single
catch block that will catch all
exceptions. If your handling depends on the type of the exception, then
the exception handler will have to inspect the name to determine the type of the
exception.Object.prototype makes that method available
to all objects. This also works for functions, arrays, strings, numbers,
regular expressions, and booleans.Function.prototype, we can make a method
available to all functions:Function.prototype.method = function (name, func) {
this.prototype[name] = func;
return this;
};
Function.prototype with a method method, we no longer have to type the
name of the prototype property. That
bit of ugliness can now be hidden.integer method to Number.prototype. It uses either Math.ceil or Math.floor, depending on the sign of the
number:Number.method('integer', function ( ) {
return Math[this < 0 ? 'ceil' : 'floor'](this);
});
document.writeln((-10 / 3).integer( )); // −3
String.method('trim', function ( ) {
return this.replace(/^\s+|\s+$/g, '');
});
document.writeln('"' + " neat ".trim( ) + '"');
trim method uses a regular
expression. We will see much more about regular expressions in .var hanoi = function hanoi(disc, src, aux, dst) {
if (disc > 0) {
hanoi(disc − 1, src, dst, aux);
document.wr