Errata

JavaScript: The Definitive Guide: Rough Cuts Version

Errata for JavaScript: The Definitive Guide: Rough Cuts Version

Submit your own errata for this product.

The errata list is a list of errors and their corrections that were found after the product was released.

The following errata were submitted by our customers and have not yet been approved or disproved by the author or editor. They solely represent the opinion of the customer.

Color Key: Serious technical mistake Minor technical mistake Language or formatting error Typo Question Note Update

Version Location Description Submitted by Date submitted
Printed Page xiv,722-1016
entire page

Confirming Alan Stearns report of Sep 21, 2011: All the placeholder text in the Core JavaScript Reference and Client-Side JavaScript Reference sections in my printed book are printed with all the same graphic character.

Joseph Michaud  Nov 07, 2011 
PDF Page Page 486
2nd paragraph,2nd line of comments

The text


*To make use of a Keymap, call its install() method, passing an HTML element,
* such as the document object. install() adds an onkeydown event handler to
* the specified object.

change to

*To make use of a Keymap, call its install() method, passing an HTML element,
* such as the document object. Install() adds an onkeydown event handler to
* the specified object.

The dot behind object should be a stop rather than expression.3Q((。(^_^)。))

zhang shaofeng  Jan 28, 2015 
PDF Page n/a
In chapter 7, section "Iterating Arrays"

This is regarding the following code example:

for(var i = 0; i < a.length; i++ {
if(!a[i]) continue; // Skip null, undefined and nonexistent elements
}

I think it's fair to say the code sample is somewhat misleading, because it will not work as intended if an array element contains a boolean value of false. The comment in the example says "Skip null, undefined, and nonexistent elements." That statement is correct, but it doesn't mention that if a[i] evaluates to false it will also be skipped via the continue statement.

WMullen  Apr 16, 2016 
https://www.safaribooksonline.com/library/view/javascript-the-definitive/9781449393854/rn01re15.html
array.pop()

Reported by Safari customer.

Name
Array.pop() — remove and return the last element of an array

Synopsis
array.pop()
RETURNS
The last element of array.

Description
pop() deletes the last element of array, decrements the array length, and returns the value of the element that it deleted. If the array is already empty, pop() does not change the array and returns the undefined value.

Example
pop(), and its companion method push(), provide the functionality of a first-in, last-out stack. For example:

var stack = []; // stack: []
stack.push(1, 2); // stack: [1,2] Returns 2
stack.pop(); // stack: [1] Returns 2
stack.push([4,5]); // stack: [1,[4,5]] Returns 2
stack.pop() // stack: [1] Returns [4,5]
stack.pop(); // stack: [] Returns 1

Shaowei Wu  Dec 12, 2016 
Printed Page section 20.2.3
code sample

in function getcookie, the variable of cookie is used in wrong way, my print is chinese edition.

Anonymous  Jun 22, 2017 
Chapter 5
5.5 Jumps

> The throw statement is a kind of interim return from a generator function.

I'd guess that is likely supposed to be "yield" and not "return".

Matt Whipple  Jan 25, 2021 
Chapte 5
5.5 Jumps

Meta-errata:

> The throw statement is a kind of interim return from a generator function.

s/throw/yield/ (my previous submission had the wrong target)

Matt Whipple  Jan 25, 2021 
PDF Page §8.5, on p.204
Last paragraph of the section

Typo: "within that namesapce"

Charles  Dec 04, 2022 
PDF Page p.213, end of section 8.7
Code snippet in the middle of the page, constructFunction()

The code has an error. It doesn't return any value for "scope" (expected value was "global", according to the book):


let scope = "global";
function constructFunction() {
let scope = "local";
return new Function("return scope");
}
constructFunction()();


Javascript output:
ReferenceError: scope is not defined

Anonymous  Jan 09, 2023 
Other Digital Version 4
United States

In the ePub version, the style sheet uses a fixed font size for code samples (the HTML <pre> tag). This prevents the code samples from scaling with the rest of the text as the user changes the font size settings on an eReader such as the Nook. The 10pt font size used is too large, resulting in almost every line of code wrapping and becoming unreadable. The code font should be scaled to the main document font so they resize together, as is done for some other O'Reilly books.

Bill Hensley  May 29, 2012 
PDF Page 4.12.1
1st paragraph of the section

"that exception propogates from the call to eval()."

should read "propagates" instead of "propogates"

Charles  Oct 17, 2022 
Printed Page 7
United States

refers to the object on which the method is defined

should read

refers to the object in which the method is defined

about line 13

Anonymous  Mar 17, 2015 
Printed Page 8
Last comment in code example

In the comment ?Now the Point object p?? I wouldn?t risk the use of the word ?inherits?. Perhaps ?accommodates? or ?has? would be safer.

Angelos Sphyris  Aug 05, 2013 
PDF Page 12
1.2.1

The example code fails on Chrome 28 when loaded info a browser with the file:// scheme. The access to localStorage in line 117 fails with a SecurityError: DOM Exception 18. The script works fine if you have a local webserver and can serve the page via http://

huntdesign  Aug 03, 2013 
Printed, ePub, Mobi Page 15
Line 12

at the end of the line is missing semicolon
total.innerHTML = "" should be total.innerHTML = "";

Fernando Laso  Dec 23, 2014 
Printed Page 16
Page first segment

The <canvas> page in the first paragraph into the wrong <vanvas>

Anonymous  Sep 24, 2016 
Printed Page 22
First paragraph

In the Brazilian version of the book, the word "indent" has been translated as "edentar" instead "indentar". In brazilian portuguese, "edentar" have a totally different meaning and may cause confusion.

Mariana de Paula  Oct 18, 2021 
Printed Page 24
Last paragraph on this page

The section 2.4.1 on reserved words is misleading as far as the reserved words class, const, enum, export, extends, import and super are concerned.

The second paragraph in this section says these were reserved in ECMAScript 5. In the last paragraph it says the reserved words policy has been relaxed in ECMAScript 5 and lists the above again as part of a big list of Java language keywords. Since they were said to be reserved in ECMAScript 5, they should be excluded from here.

Prasad Kukkamalla  Dec 30, 2011 
Printed Page 24
var 'pi' = 3.142 : near top of page

The text clearly shows that the greek letter 'pi' is the first
and only letter in the identifier.

This contradicts the text in the preceding paragraph.

The greek letter 'pi' may be the second or later letter of
an identifier, but not the first.

Anonymous  May 14, 2015 
Printed Page 31
fourth line

The line starts with

default, the are in base 10, ...

It should be

default, they are in base 10, ...

That is, 'the' should be replaced with 'they'.

Hugo Gabriel Eyherabide  Jan 10, 2021 
PDF Page 40
"All other values, including all objects..."

6th edition, 3.3 boolean values, the sentence "All other values, including all objects..."

My comment may seem very pedantic, but I will post it here anyway.

You said this:
--begin of quote--
The following values convert to, and therefore work like, false:

undefined
null
0
-0
NaN
"" // the empty string

All other values, including all objects (and arrays) convert to, and work like, true
--end of quote--

You didn't mention "false" in the list, so, formally, "false" is in "all other values" and so false convert to true. So, literal meaning of this sentence implies false convert to true. Yes, probably, nobody will interpret it such way, but I think this is still good idea to fix somehow the sentence. Add "false" to the list or say "All other values (excluding "false")".

Askar Safin  Aug 06, 2017 
Printed Page 41
2nd paragraph; second sentence

In the second sentence of the second paragraph on page 41 it is stated:

"The second case is less strict: ..."

Actually it is the opposite. The first case:

if (o !== null) ...

is less strict than the second case:

if (o) ...

The first case will execute the body of the if-statement only if any value other than null has been assigned to o. That is, it will execute the body of the if-statement even for undefined, 0, -0, NaN and "". Whereas the second case will execute the body of the if-statement only if o has been assigned a truthy value, that is, any value just not null, undefined, 0, -0, NaN and "".

Roman Jasmann  Feb 28, 2017 
PDF Page 44
4th paragraph

CURRENT STATE:
If two distinct string values are compared, JavaScript treats them as equal if,
and only if, they have the same length and if the character at each index is the same.

SUGGESTION:
If two distinct string values are compared, JavaScript treats them as equal if,
and only if, they have the same length and if the 16-bit value at each index is the same.

kadzme  Apr 24, 2019 
PDF Page 46
Table, "['a'] (any other array)"

The table implies that any array except for [] and single-numeric-element array such as [9] converts to non-NaN number. But this is not true. ["2"] converts to 2.

Askar Safin  Aug 07, 2017 
Printed Page 51
4th paragraph, last sentence

The punctuation surrounding the word "however" is incorrect. There should not be a comma followed by a colon:

"The conversion is not exactly the same as those explained above, however: the primitive value..."

Instead, there should be a semicolon followed by a comma:

"The conversion is not exactly the same as those explained above; however, the primitive value..."

Rob Johansen  Nov 17, 2014 
PDF Page 51
"+ , == , != and the relational operators are the only ones..."

"+, ==, != and the relational operators are the only ones that perform this special kind of
string-to-primitive conversions."

Are you sure you meant string-to-primitive here? Maybe object-to-primitive?

Askar Safin  Aug 07, 2017 
PDF Page 54
1st example

Written:
console.log(j); // j is defined, but may not be initialized

j may be not defined if typeof o != "object"

Tigran  Dec 18, 2013 
PDF Page 69
2nd pararagraph

The last sentence of the 2nd paragraph:
If you do so, JavaScript will treat the operand as a complete statement by itself and insert a semicolon before it.

I think 'before' should be 'after' so the sentence should be
If you do so, JavaScript will treat the operand as a complete statement by itself and insert a semicolon after it.

Anonymous  Aug 21, 2014 
PDF Page 69
2nd paragraph

The details of this object-to-number conversion explain why an empty array converts to the number 0

// I tested in chrome, empty array converts to empty string, not 0

Yan Ji  Apr 01, 2016 
Printed Page 77
4th paragraph

A wrong piece of code submitted by a reader ended up in the confirmed errata page. I wrote a test page with the wrong code to prove it:
----------------------------------------------------------------------------------------------
----------------------------------------------------------------------------------------------
<html>
<head>
<script>
// Copy the enumerable properties of p to o, and return o.
function copy(p, o) {
o = p || {}; // If o is falsy, use a newly created object.
for(prop in p) { // For all props in p.
o[prop] = p[prop]; // Add the property to o.
}
return o;
}

function test_copy(){

var full = {name: "joe", surname: "doe", job: "worker"};
var empty = {};

var a_copy = copy(full,empty);
console.log(a_copy);

var a_copy2 = copy(full);
console.log(a_copy2);

console.log(full===a_copy2); // -> true ... THIS IS A MISTAKE
}
</script>
</head>

<body>
<button onclick=test_copy();> RUN </button>
</body>

</html>
----------------------------------------------------------------------------------------------
----------------------------------------------------------------------------------------------
The function copy() as printed in the book is correct.

Massimiliano De Simone  Jul 18, 2015 
Printed Page 84
delete code examples in 4.13.3

...
delete o; // Can't delete a declared variable; returns false.

This statement return true on Firefox 6 & Chrome 13 outside of strict mode. And the text above the example need corrections as well.

Thanks for writing the book.

April  Sep 06, 2011 
PDF Page 103
Middle of 2nd last paragraph

Author writes:
"A newline is not allowed between the break keyword and the label name."

This to me is quite misleading as it implies that doing so will result in some sort of error., which is not the case.

Maybe the above sentence should be rephrased to say:

A newline between the break keyword and the label name will cause the label to be ignored.

Daniel David  Nov 18, 2015 
Printed Page 113
2nd paragraph

I don't know if the English Edition is wrong too, since I bought the Chinese Edition.

At 5.7 "其他语句类型“ in page 113 of Chinese Edition, it wrote that "本节讨论剩余的三种JavaScript语句——width, debugger和use strict".

"width" should be wrong, it should be "with"

Lisa  Dec 13, 2017 
Printed Page 113
1st paragraph

The sentence "The throw statement is a kind of interim return from a generator function." appears to be describing the yield statement, not the throw statement.

Brian Chhun  Apr 26, 2021 
PDF Page 123
3rd code example

The code reads as follows:

// A verbose and explicit technique
var len = undefined;
if (book) {
if (book.subtitle) len = book.subtitle.length;
}
// A concise and idiomatic alternative to get subtitle length or undefined
var len = book && book.subtitle && book.subtitle.length;

What good does if(book) and book do in these conditions knowing that they'll throw a ReferenceError if book variable is not defined? This is what I get when I run the code samples: Uncaught ReferenceError: book is not defined.

Samir Saeedi  Apr 22, 2017 
PDF Page 128
function union

/*
* Return a new object that holds the properties of both o and p.
* If o and p have properties by the same name, the values from o are used. */
function union(o,p) { return extend(extend({},o), p); }

The second sentence of the comment says that where properties use the same name, the values from o are used. I believe this should be in reverse - properties using the same name use the values from p, not o.

For example:

var stock = {name: "AT&T", shares: 100};
var quote = {name: "ATT", shares: 50, price: 32.5};
extend(stock,quote);

returns:
({name:"ATT", shares:50, price:32.5})

Notice that the properties from quote overwrite the properties in stock with the same name.

Kory  Oct 04, 2014 
128
2nd sample code

set r(newvalue) {
var oldvalue = Math.sqrt(this.x*this.x + this.y*this.y);
var ratio = newvalue/oldvalue;
this.x *= ratio;
this.y *= ratio;
},

in the above block shouldn't "newvalue" be defined first like x and y in the new object created?

Prashanth Devadas  Aug 23, 2016 
Printed Page 140
2nd of 6.8.3

Printing error
not Object.isExtensible( ) but Object.isExtensible( )

alan fan  Feb 25, 2019 
Printed Page 142
var undefs = [ , , ] ; // length 2 : near top of page

When testing ....

var undefs = [ , , ] ;

The length of the array was 3 .

Anonymous  May 14, 2015 
Printed Page 143
2

The original:
“What is special about arrays is that when you use property names that are non-negative integers less than 2^32, the array automatically maintains the value of the length property for you.”
Should be modified as:
Less than 2^32 – 1

Lucio Lu  Feb 04, 2020 
PDF Page 144
3rd paragraph of 7.3

It reads as follows:
"Arrays that are sufficiently sparse are typically implemented in a slower, more memory-efficient way than dense arrays are, and looking up elements in such an array will take about as much time as regular object property lookup."
How is it both "slow" and "memory-efficient"? I think it should be memory-intensive.

Samir Saeedi  Apr 23, 2017 
Printed Page 145
2nd paragraph

The original:
“What is special about arrays is that when you use property names that are non-negative integers less than 2^32, the array automatically maintains the value of the length property for you.”
Should be modified as:
Less than 2^32 – 1

Tye Lokka  Feb 04, 2020 
Other Digital Version 151
First example of splice in the paragraph 7.8.6

var a = [1,2,3,4,5,6,7,8];
If we call the method splice() on this array, the array itself we'll be [1, 4, 5, 6, 7, 8], not [1,4].

Sergej Osokin  Apr 05, 2016 
PDF Page 152
Last paragraph

In the last paragraph of section 6.10.6, the snippet comment reads :

"The expression "random.octet", for example, yields a random number between 0 and 255 each time it is evaluated."

However, the range is 0-256 if Math.random() evaluates to 1: Math.floor(Math.random()*256);

Here's the full snippet of the book:
// This object has accessor properties that return random numbers.
// The expression "random.octet", for example, yields a random number
// between 0 and 255 each time it is evaluated.
const random = {
get octet() { return Math.floor(Math.random()*256); },
get uint16() { return Math.floor(Math.random()*65536); },
get int16() { return Math.floor(Math.random()*65536)-32768; }
};

Charles  Nov 13, 2022 
Printed Page 156
2nd Code example , undeneath 6th paragraph

This concerns the inherit function in Javascript - The Definitive
Guide 6th edition:

var obj = { p1: 0, p2: new Array(10)}

var tab = [inherit(obj), inherit(obj)];

tab[0].p1 = 1;
tab[0].p2[0] = 'F';

tab[1].p1 = 2;
tab[1].p2[0] = 'S';

Note that for for both entries in tab, p2[0] is set to 'S'!

Anonymous  Oct 17, 2011 
Printed Page 165
1st paragraph

The book states "A function declaration statement actually declares a variable and assigns a function object to it. A function definition expression, on the other hand, does not declare a variable."

I believe these are reversed. A function declaration does not declare a variable, while a function definition expression does.

The following is an example of a function definition expression where the function object IS assigned to a variable:

var tensquared = function(x) { return x*x; };


And the following is an example of a function declaration statement where the function object is assigned to an identifier, not to a variable:

function distance( x1, x2 ) { return x2 - x1; };

Anonymous  Mar 12, 2013 
Printed Page 165
1st paragraph

i found the following phrase in the book:

"A function definition expression, on the other hand, does not declare a variable."

I would like to know whether it is a mishap or not.

Thanks

Anonymous  Apr 29, 2014 
Printed Page 168
10th line (including the example)

The line starts with

<code>true</code>

It was most likely intended to be the value 'true' formatted as <code> (same as the value 'false') but it was not rendered as such.

Hugo Gabriel Eyherabide  Jan 10, 2021 
Printed Page 169
bottom

What is at the bottom of page 169 is not a bug. Rather, it is a good example. There, one can read:

"Example 8-5, in ? 8.7.4, includes" ...

Unfortunately, the paragraph number is very often missing at other places in the book, when referring to an example. This makes it more difficult to find the example.

Saašha Metsärantala  Dec 29, 2011 
PDF Page 178
factorial function

The factorial function always returns NaN !

Here is the function:

function factorial(n) {
if (isFinite(n) && n>0 && n==Math.round(n)) { // Finite, positive ints only
if (!(n in factorial)) // If no cached result
factorial[n] = n * factorial(n-1); // Compute and cache it
return factorial[n]; // Return the cached result
}
else return NaN; // If input was bad
}

So if I invoke factorial(1) - I get 1 * facttorial(0) = 1 * NaN = NaN

Daniel David  Dec 15, 2015 
Printed Page 178
Section 8.4.1

This looks like a big change for ES6.

Properties cannot be added to a function, they are undefined as per the following sources:

https://www.tutorialspoint.com/add-a-property-to-a-javascript-object-constructor
https://www.w3schools.com/js/js_object_prototypes.asp

The above has been validated in the following environments supporting ES6:

node.js
v12.11.1
MacOS v10.12.6
Safari
v12.1.2

The following sections of text are impacted:

p178 8.4.1 Defining Your Own Function Properties
p200 Example 9-1
p205 9.3 Java-Style Classes in JavaScript
p206 Example 9-3

Andrew Gallant  Oct 15, 2019 
Printed Page 179
Example 8-3

In some ways, the extend() function in example 8-3 is a step backwards. It produces the behavior of the simpler version of extend() on pg. 127 rather than building on the improved version on pg. 134. Namely it does not handle property attributes properly and overwrites existing properties of the object o.

David Sletten  Dec 30, 2012 
Printed Page 186
First sentence section 8.7.2

The book says: "Every function has a prototype property that refers to an object known as the prototype object." The standard requires this of (most) functions defined by the user, but it does not appear to be true of most built-in functions.

According to Chrome (23.0.1271.101) and Safari (5.1.7) none of the following function objects have a 'prototype' property: the function prototype (i.e., Function.prototype), Object.create, String.prototype.charAt, Date.prototype.getMilliseconds, Date.now

In fact, it may be the case that no built-in function other than the obvious constructors (Object(), Date(), Array(), ...) has a prototype associated with it.

Section 13.2 of ECMA-262 discusses the process of creating functions. In particular, steps 16 and 18 refer to the creation of a corresponding prototype object and its association with the new function through its 'prototype' property. The section ends with the following note: "A prototype property is automatically created for every function, to allow for the possibility that the function will be used as a constructor." This note may shed some light on why built-in functions don't have 'prototype' properties since they will never be used as constructors. It is more efficient to avoid creating the unnecessary prototype objects in this case.

Furthermore, section 15.3.5.2 discusses the special case of functions creted by means of bind(): "Function objects created using Function.prototype.bind do not have a prototype property." So it's not even true that all user-defined functions have a 'prototype' property.

David Sletten  Dec 22, 2012 
PDF Page 187
bottom of page 187 / top of page 188

This code appears at the bottom of page 187..
function trace(o, m) {
var original = o[m];
o[m] = function() {
console.log(new Date(), "Entering:", m);
var result = original.apply(this, arguments);
console.log(new Date(), "Exiting:", m);
return result;
};
}

Should the code be modified with the two changes noted below?..
function trace(o, m) {
var original = m; // change o[m] to m
o[m] = function() {
console.log(new Date(), "Entering:", m);
var result = original.apply(this, arguments);
console.log(new Date(), "Exiting:", m); Log message.
return result;
};

return o[m]; // add this line
}

// by making the above edits, the trace function could then be used as follows..

var myObj = {
myMethod : function(x,y) {return x + y}
};

var test = trace(myObj, myObj.myMethod);

test(1,2); // output => logging messages and result (3)


Gerald LeRoy  Aug 16, 2014 
PDF Page 191
Last paragraph

"JavaScript is not a functional programming language like Lisp or Haskell". I disagree. Moreover, JavaScript is inspired by Scheme (Lisp dialect). Original JS is essentially Scheme with Java syntax

Askar Safin  Aug 26, 2017 
PDF Page 192
Function defining map method if it doesn't exist

Why are the extra i and a included in the call parameters/arguments, positions 3 and 4?

Replace this current line
if (i in a) results[i] = f.call(null, a[i], i, a);

with this
if (i in a) results[i] = f.call(null, a[i]);

or this
if (i in a) results[i] = f.call(o || null, a[i]); //this is from the errata version page, excluding the i and a

seems to work to work to produce a new array. I am just trying to understand if there is an occasion where the extra i and a are needed?

Anonymous  Mar 29, 2016 
Printed Page 192
Third code block

The ECMAScript 3 reduce() behaves differently to ECMAScript 5 Array.prototype.reduce() if an initial value is not supplied and:

* a.length=1 and a contains no elements (Returns undefined, but ES5 throws)
* a.length>1 and only a[a.length-1] exists (Throws, but ES5 returns a[a.length-1])

Fix listed below.

------------------------------------------------------------------------------------------------
TEST SCRIPT
------------------------------------------------------------------------------------------------

//**************************************************************************
// reduce() as listed in book, but split into ES3/ES5 versions for testing
//**************************************************************************

var reduceES5 =
function(a, f, initial) { // If the reduce() method exists
if(arguments.length > 2)
return a.reduce(f,initial);
else
return a.reduce(f);
};

var reduceES3 =
function(a, f, initial) {
var i=0, len=a.length, accumulator;

// Start with the specified initial value, or the first value in a
if(arguments.length > 2)
accumulator = initial;
else { // Find the first defined index in the array
if(len==0)
throw TypeError();

while(i<len) {
if(i in a) {
accumulator = a[i++];
break;
} else i++;
}

if(i==len && len>1)
throw TypeError();
}

// Now call f for each remaining element in the array
while(i < len) {
if(i in a)
accumulator = f.call(undefined, accumulator, a[i], i, a);
i++;
}

return accumulator;
};

//**************************************************************************
// Modified Array.prototype.toString()
// Shows non-existent elements as 'x'
//**************************************************************************

Array.prototype.toString = function() {
var str = "";
for (var i=0; i<this.length; ++i) {
if(i in this)
str += this[i];
else
str += 'x';
if(i<this.length-1)
str += ',';
}
return str;
};

//**************************************************************************
// Test code
//**************************************************************************

var testArrays = [ [,], [,1], [,,2] ];

var add = function(x,y){return x+y;};

var resES3 = [];
var resES5 = [];
var resES30 = [];
var resES50 = [];

var res, i;

// Call reduce() for each test case
for(i=0; i<testArrays.length; ++i) {
try { res = reduceES3(testArrays[i], add); }
catch(err) { res = "Throws" }
resES3.push(res);

try { res = reduceES5(testArrays[i], add); }
catch(err) { res = "Throws" }
resES5.push(res);

try { res = reduceES3(testArrays[i], add, 0); }
catch(err) { res = "Throws" }
resES30.push(res);

try { res = reduceES5(testArrays[i], add, 0); }
catch(err) { res = "Throws" }
resES50.push(res);
}

// Output results
for(i=0; i<testArrays.length; ++i) {
if( resES3[i]!==resES5[i] && !(resES3[i]!==resES3[i] && resES5[i]!==resES5[i]) )
bold = true;
else
bold = false;

if( resES30[i]!==resES50[i] && !(resES30[i]!==resES30[i] && resES50[i]!==resES50[i]) )
bold0 = true;
else
bold0 = false;

document.write( (bold?"<b>":"") + "reduceES3([" + testArrays[i].toString() + "], add) = " + resES3[i] + (bold?"</b>":"") + "<br/>" );
document.write( (bold?"<b>":"") + "reduceES5([" + testArrays[i].toString() + "], add) = " + resES5[i] + (bold?"</b>":"") + "<br/>");
document.write( (bold0?"<b>":"") + "reduceES3([" + testArrays[i].toString() + "], add, 0) = " + resES30[i] + (bold0?"</b>":"") + "<br/>");
document.write( (bold0?"<b>":"") + "reduceES5([" + testArrays[i].toString() + "], add, 0) = " + resES50[i] + (bold0?"</b>":"") + "<br/><br/>");
}

------------------------------------------------------------------------------------------------
FIXED reduceES3()
------------------------------------------------------------------------------------------------

var reduceES3 =
function(a, f, initial) {
var len=a.length, i, accumulator;

// Start with the specified initial value, or the first value in a
if(arguments.length > 2) {
i=0;
accumulator = initial;
} else { // Find the first defined index in the array
for(i=0; i<len && !(i in a); ++i);

if(i<len)
accumulator = a[i++];
else
throw TypeError();
}

// Now call f for each remaining element in the array
for(;i<len; ++i) {
if(i in a)
accumulator = f.call(undefined, accumulator, a[i], i, a);
}

return accumulator;
};

Jonathan Dodd  Jan 23, 2017 
Printed Page 192
3rd section

I believe that this line... if (i in a) results[i] = f.call(o || null, a[i], i, a);

should either be this: if (i in a) results[i] = f.call(o || null, a[i]);

or this: if (i in a) results[i] = f.apply(o || null, [a[i], i, a]);

Gerald LeRoy  May 17, 2018 
Printed Page 193
16th line of code from top of page

From the Confirmed Erata page:

Description:
The "if (i == len)" statement causes reduce to throw a TypeError when it is called with an array containing a single element and no initial value.

Note from the Author or Editor:
Change if (i == len) to if (i == len && len > 1)

Comment/Question:
Even with the above change, an error is still thrown for sparse arrays, for example [ , , 1].

Is the line (i == len && len >1) even needed? When that line is commented out, the code appears to work for all cases.

Gerald LeRoy  Aug 31, 2014 
PDF Page 193
Last paragraph

The paragraph provides a way to easily test for an existing array, and to assign it to a variable, or, if no array exists, create a new one: a = a || [];
The problem is the explanation uses the word "object" instead of "array":

"In this case, if any object is passed as the second argument, the function will use that object"

Charles  Dec 02, 2022 
Printed Page 194
Middle of page

The compose() function only works for 2 functions. Here is a version that works with an arbitrary number of functions. It is derived from Paul Graham's book "On Lisp" (pg. 66):
function compose() {
if ( arguments.length === 0 ) {
return function(x) { return x; }; // Identity
} else {
var fns = Array.prototype.concat.apply([], arguments);
var fn1 = fns.pop();
return function() {
return fns.reduceRight(function(x, f) { return f.call(this, x); }, fn1.apply(this, arguments));
};
}
}

David Sletten  Jan 12, 2013 
Printed Page 194
Middle of page

Oops. The compose() function I submitted will work as expected since all of the arguments are functions, but the conversion of arguments to an Array will not work in general:
var fns = Array.prototype.concat.apply([], arguments);

The problem is that concat() flattens nested Array elements.

Here is a more general solution:
var fns = Array.prototype.slice.call(arguments, 0);

David Sletten  Jan 13, 2013 
Printed Page 194
Middle of page

Oops again. I misidentified the problem above. In fact, concat() does not flatten nested elements. It's the use of apply() that is the problem. It causes the elements of arguments to be passed directly to concat(), which then flattens them as top-level args:
Array.prototype.concat.apply([], [[1, 2], [3, 4]]) => [1, 2, 3, 4]

David Sletten  Jan 13, 2013 
PDF Page 194
general example

There is this comment:
// The returned function h passes all of its arguments to g, and then passes

There is no function h, so which function does h refer to?

Anonymous  Mar 30, 2016 
Printed Page 195
Top of page

The partialRight() function is of limited use in JavaScript. In its most basic usage it does return a function whose rightmost argument(s) is fixed:
var square = partialRight(Math.pow, 2);
square(8) => 64

However, this partial function does not play nice with the new higher-order array functions such as map(), reduce(),... The problem is that JavaScript defines these functions in an idiosyncratic way.

Consider map(). In most languages, such a function traverses a sequence of values and yields a new sequence produced by applying a given function to each element of the sequence in turn. The key is that the function used to perform the mapping takes a single value, namely each element one at a time.

However, JavaScript's map() function passes three arguments to the mapped function: the element, its index, and the Array object itself. When a function created by partialRight() receives these three arguments it appends the fixed argument to the end and invokes the underlying function.

Suppose that we evaluate the following expression:
var a = [2, 3, 4];
a.map(square)

Rather than calling Math.pow(2, 2) with the first element and the fixed value 2, we actually get Math.pow(2, 0, a, 2). Math.pow() ignores the last 2 arguments and simply returns:
Math.pow(2, 0) => 1

Likewise, the 2nd element results in Math.pow(3, 1, a, 2), which evaluates:
Math.pow(3, 1) => 3

Only the 3rd element coincidentally produces the expected value: Math.pow(4, 2, a, 2) => 16

This problem can perhaps be mitigated by examining the 'length' property of the function being fixed:
function partialRight(f) {
var args = Array.prototype.slice.call(arguments, 1);
var length = f.length - args.length;
return function() {
return f.apply(this, Array.prototype.slice.call(arguments, 0, length).concat(args));
};
}

This modified partialRight() works with map() and square() as in the above example, but I haven't tested it exhaustively.

One obvious issue with relying on the function's 'length' property is that this only reflects the number of 'required' arguments. A varargs function would accept its arbitrary number of args via the 'arguments' object regardless of the value of 'length'. However, it doesn't make sense to apply partialRight() to a varargs function anyway.

David Sletten  Jan 15, 2013 
PDF Page 213
top of page

The book reads:
If we define a constructor using an unnamed function definition expression, the getName() method will return an empty string.

That's just not true. In Chrome I wrote this:
var c = function(x){this.x=x}
var o = new c(1);

Querying o.constructor.name, the result is: "c".
Defining and using the getName() function of yours, the result is still the same, o.constructor.getName() returns "c".

Samir Saeedi  Apr 25, 2017 
PDF Page 215
Example 9-6

Please send me an example of how to test this script. I have tried to follow it and have no idea of how to use it. For example, do I input an object or an array and how to trigger the script? With a new edition it would be helpful if all examples include items that demonstrate how the script works, like with example 9-1. I realize most examples include examples uses and output, but this one has me lost. Thanks.

Anonymous  Mar 31, 2016 
Other Digital Version 225
generic equals function

An additional constraint on the classes for which the equals function works is that they have a fixed set of properties. If the properties of objects of the class are not predetermined, "that" could have properties that "this" does not have. In this case, the equals function would be more akin to a subset predicate.

Even for classes with such a constraint, users of such a class can make the function non-reflexive by adding a property to one object.

function Obj(val) { this.val = val; }
Obj.prototype.equals = generic.equals;

var obj1 = new Obj(3);
var obj2 = new Obj(3);
obj1.equals(obj2) // => true
obj2.equals(obj1) // => true

obj2.extra = 7;
obj1.equals(obj2) // => true
obj2.equals(obj1) // => false

Evan  Sep 28, 2011 
Printed Page 225 Chapter 9.6.5
Example 9-9.

The code for the equals function does not consider the case that object "that" has an own property, that "this" does not have.
If "that" has an own property "b" that "this" does not have, both objects can still be equal, because only the set of own properties from the "this" object is checked for existence and equality with respect to the "that" object but not vice versa.

// Tests for equality by comparing the constructors and instance properties
// of this and that. Only works for classes whose instance properties are
// primitive values that can be compared with ===.
// As a special case, ignore the special property added by the Set class.
equals: function(that) {
if (that == null) return false;
if (this.constructor !== that.constructor) return false;
for(var name in this) {
if (name === "|**objectid**|") continue; // skip special prop.
if (!this.hasOwnProperty(name)) continue; // skip inherited
if (this[name] !== that[name]) return false; // compare values
}
return true; // If all properties matched, objects are equal.

Michael Aakolk  Nov 25, 2013 
Printed Page 228
United States

The book uses two different and incompatible definitions for the term "method chaining":
1. The practice of writing methods to return the value of the receiver (this) so that subsequent method calls involving the same object can be chained onto the current method call. (pg. 169)
2. The act of a method on a subclass prototype invoking the corresponding overridden method on the superclass prototype in order to perform some of its work. (pg. 228, 230 and following).

The first definition is in widespread use, but the second seems to be idiosyncratic. In fact, page 169 warns not to confuse method chaining with the topics discussed in section 9.7.2 (pg. 230).

Some other JavaScript authors use the terms "constructor stealing" or "constructor borrowing", and to be fair, apparently the Java and C++ communities do use the term "constructor chaining". But the book's overloading of the term "method chaining" is confusing.

Incidentally, the footnote on page 169 refers to Martin Fowler's website to point out the origin of the term. This link is dead. The following link simply provides a short blurb: http://martinfowler.com/dslCatalog/methodChaining.html
It appears that Martin Fowler wants the reader to refer to ch. 35 of his DSL book.

David Sletten  Feb 24, 2013 
Printed Page 229
1st paragraph of section 9.7.1

The text says, "If an object O is an instance of a class B and B is a subclass of A, then O must also inherit properties from A. We arrange this by ensuring that the prototype of B inherits from the prototype of A."

An example is then given:

B.prototype = inherit(A.prototype);
B.prototype.constructor = B;

I disagree with this text. If B is a subclass of A, then I would think that A is the prototype of B rather than A.prototype. If B's prototype equals A's prototype as instructed in the text, then B will only have access to the members of A's prototype. B will not have access to the additional members of A. Consequently, B will not be a true subclass of A. In fact, A and B will be subclasses of some other object (namely the prototype of A). I think the example should be:

B.prototype = inherit(A);
B.prototype.constructor = B;

Furthermore, I am not convinced that the second line is really needed. B.prototype can only be assigned if B exists. If B exists, it will already have a constructor set to B. Assigning a new prototype to B should not change the constructor of B.

Would appreciate any thoughts on this.

Thank you.

David Cox  Jan 31, 2012 
Printed Page 233
example first line after opening comment

the paragraph before the example talks about the advantage of composition over inheritance. Next the example starts with:

var FilteredSet = Set.extend(...

in my opinion this makes the example very hard to understand as it uses subclassing AND composition of Set. If you want to give an example about composition then it should be only about composition. In my opinion it should be:

var FilteredSet = Function.extend(...

I tested this and it works for me. thnx, Arnoud

PS I can understand it from a perspective that you want a FilteredSet to be an instance of Set but it that case it needs to be clarified why you extend Set instead of Function.

Anonymous  Jan 06, 2014 
Printed Page 234
Top of page

The NonNullSet 's' created by means of FilteredSet is not identical to the earlier definition since the filter tests x !== null. This only weeds out null values and not undefined values. The earlier implementation effectively filters using the less strict x != null, which applies to undefined values as well.

David Sletten  Feb 27, 2013 
Printed Page 238
Example 9-17

Example 9-17 would be less cluttered if the 'enumerable', 'configurable', and 'writable' property attributes were simply omitted. The preceding text could remind the reader that for a new property defineProperty() assigns the value false to unspecified attributes (pg. 132).

David Sletten  Mar 09, 2013 
Printed Page 239
first line

Current:
...you can create a SUPERCLASS simply by adding an extends clause...

Correction:
...you can create a SUBCLASS simply by adding an extends clause...

Adam C  Oct 22, 2020 
Printed Page 244
2nd paragraph

Was it was meant to say "The returned object defines four useful methods:
toString(), descriptors(), hide(), and freeze().", not show() as the last method.

Also, was object should be plural in the 2nd comment below this?

Thank you. Great book!

Jim Olson  Sep 19, 2016 
Printed Page 245
the 13th line from the bottom, in the function 'toString()' of Example 9-23

to Author:
calling the function toString() of such an object below leads to an error:
var testa = {
A:1,
get a(){return this.A},
set a(x){this.A = x}
};
the output of the code " testa.properties().toString() " is:
"{
A: 1,
readonly accessor a
}"
But obviously, "a" is not readonly. Thats's because the 'writable' property of 'a' is ''undefined' which gets a Boolean false. And the code "!desc.writable" of 13th line from bottom makes output of function totSring() have an extra "readonly".
Both Chrome 39 and Firefox 43 tested.

Can Zheng  Dec 06, 2016 
PDF, ePub, Mobi, Page 251
4th paragraph

"var pattern = /s$/ ;

This line creates a new RegExp object and assigns it to the variable pattern . This particular RegExp object matches any string that ends with the letter “s.” This regular expression could have equivalently been defined with the RegExp() constructor like this:"

The period isn't part of the match so it should be moved after the closing quotes to end the sentence as follows:

"This line creates a new RegExp object and assigns it to the variable pattern . This particular RegExp object matches any string that ends with the letter “s”. This regular expression could have equivalently been defined with the RegExp() constructor like this:"

Alfred Myers  Jul 01, 2019 
Printed Page 270
last two lines on page

Due to changes in 2015 that made let compliant with the final ES6 standard (https://blog.mozilla.org/addons/2015/10/14/breaking-changes-let-const-firefox-nightly-44/) the code below no longer behaves as described in the book

let x = 1;
for (let x = x + 1; x < 5; x++) {
console.log(x); // prints 2, 3, 4
}

The above code no longer prints 2, 3, 4. Depending on the browser being used, the page error varies ("ReferenceError: x is not defined", "can't access lexical declaration `x' before initialization", etc.)

Gerald LeRoy  Feb 12, 2019 
Printed Page 308
7th paragraph

The erroneous term 'CSS class' crops up in the book in several places.

It's not a 'CSS class', it's an HTML element 'class' attribute. 'HTML class' would perhaps be a better shorthand way to refer to it.

Given that the book is so excellent in its terminological accuracy throughout, this term should be replaced with something better.

A quick search through the PDF version of the book finds many other occurrences, of which the following are a sample:

page 309: 2nd paragraph 'CSS classes'
page 364: section 15.2, 4th bullet point 'CSS class'
page 437: section 16.5 heading contains 'CSS Classes'
page 525: 1st paragraph 'CSS Class
page 532: section 19.2.3 heading contains 'CSS Classes'

The term also appears in comments in sample code.

Alan Rew  Mar 29, 2012 
Other Digital Version 309
Example 13-1

Example 13-1 is somewhat misleading. The loop through each element whose class is "reveal" suggests that clicking on the first "handle" child of each such element will reveal the element containing the handle. However, since each onclick handler shares the same elt variable, the only elements that will be revealed are those in the final element with class "reveal".

Since the example contains only a single element whose class attribute is "reveal", the behavior is fairly intuitive. Adding a second or third "reveal" element might cause some surprises.

Evan  Oct 06, 2011 
Printed Page 323
5th paragraph

Chinese printed version.
Just one small typo.
addEventListaner()
This should be:
addEventListener()

zhiguang  Oct 19, 2014 
Printed Page 324
Last paragraph

In the last paragraph you wrote:

"This timeline does not specify ... when the web browser must start responding to user input events...user input events might be fired before the event-driven phase..."

However step 8 of the timeline states:

"From this point on event handlers are invoked .. in response to user input events..."

Patrick Fischer  Sep 07, 2012 
Printed Page 359
1st paragraph, last sentence

AS IS: "than the return value"
TO BE: "then the return value"

Thierry Tung  Dec 04, 2020 
Printed Page 362
HTML code example

<html>
<head>
<title>Sample Document</title>
</head>
<body>
<h1>An HTML Document</h1>
<p>This is a <i>simple</i> document.
</html>

As has already been noted the closing </body> tag is missing from the code example above.

Also missing is the closing </p> tag, which should appear as so:

<p>This is a <i>simple</i> document.</p>

winst  Mar 12, 2015 
Printed Page 375
6yh paragraph

HTMLElement defines properties for the universal HTTP attributes

should be:

HTMLElement defines properties for the global HTML attributes

as stated here:

http://www.w3.org/TR/html-markup/global-attributes.html

Anonymous  Mar 11, 2015 
PDF Page 381
Last code example

if (n.nodeType == 3 || n.nodeTyep == 4)
instead of
if (n.nodeType == 3 || n.nodeType == 4)

Askar Safin  Oct 19, 2017 
PDF Page 385
Example 15-5

"Setter__" was used in the comments instead of "__defineSetter__"

Anonymous  Apr 16, 2015 
Printed Page 391
Bottom

Function getViewportSize treats window.innerWidth/Height and document.documentElement/body.clientWidth/Height as equivalent but in fact they are different: innerWidth/Height includes space covered by scrollbars while clientWidth/Height does not.

I confirmed this on my system, and you can also find it here:
http://www.quirksmode.org/mobile/viewports.html
(search for heading "Two property pairs")

Christoph Nahr  Mar 03, 2013 
Printed Page 399
4rd

With this form, you might refer to the array of radio button elements like this:
var methods = document.forms.shipping.elements.method;
Note that <form> elements have an HTML attribute and corresponding JavaScript
property named ?method?, so in this case, we must use the elements property of the
form instead of directly accessing the method property.


why must use the elements property of the form instead of directly accessing the method property.

because of "Remember that when you index an HTMLCollection
with a name and more than one element shares that name, the returned value is an
array-like object that contains all matching elements"
when i do it
var methods = document.forms.shipping.method;
have same result?


Anonymous  Jun 01, 2012 
Printed, PDF Page 439
CSSClassList.prototype.contains function (24th line)

classes.search( "\\b" + c +"\\b" ) != -1 is not a reliable solution, e.g.:
"x-list-header-inner".search("\\bx-list-header\\b") == 0 while
"x-list-header-inner" != "x-list-header"

Anonymous  May 10, 2012 
Printed Page 460
Section 17.3.1

The method for getting to the event object in an event handler which is defined inline as a property of the target element does not work in Firefox.

You should pass arguments[0] to the handler which seems to work across all browsers

See this demo:

<!DOCTYPE html>
<html>
<body>
<script>
function handler(event){
event = event || window.event;
alert("Type of event:" + event.type);
}
</script>
<button onclick="handler(arguments[0]);">Click on me for event in all browsers!</button>
<button onclick="handler();">Click on me for error in Firefox!</button>
</body>
</html>

Semmel  Nov 16, 2012 
Printed Page 468
2nd paragraph

Text says: "It is important to note that mousemove and mouseup handlers are registered as capturing event handlers."

Both events are registered with document as target of the event. The event handlers moveHandler and upHandler both stop propagation. To me it seems that (because document is at the top of the DOM tree) it is NOT important whether error handling is bubbling (bottom up) or capturing (top down). Motion in either direction begins and ends at document.

So the questions is: why is capturing important?

PS. I tried the example with bubbling on and off and I don't see any difference in handling the drag.

Paul E.S. Wormer  Dec 28, 2011 
Printed Page 494
Example code in "XMLHttprequest in IE6" box

The ActiveXObject "Msxml2.XMLHTTP.3.0" could usefully be replaced by "Microsoft.XMLHTTP". As the former always points to the latter, nothing would be lost by this and even older versions of the IE browser would be supported.

If this change was made then the title of the box would need to be updated to "XMLHttprequest in IE5 and IE6".

Martin Leese  Jan 22, 2013 
Printed, PDF Page 505
Example 18-9.

The example does not upload a file via POST. XHR doesn't append the file to the request body.

Browsers Tested (on Ubuntu 12.10):
Google Chrome 26.0.1410.63
Mozilla Firefox 20.0

John Wesley  Jul 08, 2013 
Printed, Page 673
4th paragraph, just before screenshot

Not so much a mistake as an alternative.

"Second, Firefox 4 no longer fires a popstate event for newly loaded pages that do not have any saved state. This second change means that the example below does not work quite right in Firefox 4."

Firefox 4 does fire the pageshow event, so it works right if you bind popState to that. I added this on line 6 of the listing:

window.onpageshow = popState;

Rob Crowther  Aug 10, 2011 
PDF Page 685
Examples 22-6 and 22-7

I get the following error when I try to run Examples 22-6 and 22-7 on Chrome browser:
"Uncaught DOMException: Failed to execute 'getImageData' on 'CanvasRenderingContext2D': The canvas has been tainted by cross-origin data."

Samir Saeedi  May 10, 2017 
Printed Page 719
Arguments entry

The reference section entry for Arguments neglects any mention of the 'caller' property introduced on pg. 173.

David Sletten  Apr 06, 2013 
PDF Page 790
Toward the bottom

The author asserts that - quote:

Math.max()
Returns the larger of two numbers.
Math.min()
Returns the smaller of two numbers

The above is quite misleading, as it implies that these functions will only inspect the first 2 arguments - which is of course incorrect.

Instead, see the definition on MDN:
"The Math.min() function returns the smallest of zero or more numbers." and
The Math.max() function returns the largest of zero or more numbers.

Daniel David  Nov 10, 2015 
PDF Page 849
top of the page

An assertion is made that String.substr() is deprecated.

I believe that this is a mistake because I could not find any written evidence in the spec or elsewhere that is it deprecated.


Daniel David  Nov 10, 2015 
Printed, Mobi, Page 857
1st paragraph

The second sentence in the paragraph says:

"It includes entries for important client-side JavaScript object such as Window, Document, [...]"

"object" should be "objects".

Terrific book by the way, one of the best.

Mark Giffin  Jan 10, 2015 
Printed Page 951
Third entry from the bottom of the page

offsetParent() is listed in the section on jQuery Element methods, but it's also listed in the previous section on jQuery Selection methods (which is where it properly belongs).

Joshua Davies  Mar 18, 2014 
Printed Page 983
7th paragraph (double value)

Second sentence reads, "This property mirrors the value attribute."
This entire paragraph is *about* the value attribute, so how can it mirror itself? Was there supposed to be something else that it mirrored, or was it supposed to be mirrored by something else? Position possibly? It makes determination of which attribute to remove to change determinate/indeterminate confusing.

Charles Hernandez  Aug 15, 2015 
Printed Page 1020
omition of !! operator

there is no mention of the cast to boolean operator !!

I noticed this when attempting to use this book to determine what the !! operator was in reading the source code for the com.google.gwt.dom.client.Node class

Anonymous  May 13, 2013