Errata

JavaScript Patterns

Errata for JavaScript Patterns

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 51
Vereinigte Staaten

reg.foo = "baz" should be => reg.foo = "bar"

Savio van Hoi  Jan 23, 2014 
Printed Page 51
Code sample on lower half of page

function getRE() {
var re = /[a-z]/;
re.foo = "bar";
return re;
}

var reg = getRE(),
re2 = getRE();

console.log(reg === re2); //true according to book
reg.foo = "baz";
console.log(re2.foo); //baz according to book

The author says the first console.log will be true and the second will be baz, however, the values turn out to be false, and bar all the way back into IE 8 consoles, which I did not think included ECMAScript 5 which is where they claim the behavior changes.

Richard Harrington  Aug 18, 2014 
Printed Page 59
Second line of the final code sample

Line two in the code example at the bottom of page 59 reads 'pased,' but should really read 'passed.'

Richard Harrington  Aug 18, 2014 
Printed Page 66
code snippet

in the new version of findNodes code:
var findNodes = function (callback, callback_obj) {
if ( typeof callback === "string" ) {
callback = calbback_obj[callback];
}

the callback parameter passed is a string, and there is something behind the sense is it gets the method of object using its string. I think it worth to mention it.

I lost at this point after some searching for the using [] to get the method.

Cheng Luo  Dec 19, 2012 
Printed Page 66
Asynchronous Event Handlers

The code example mentioned in Asynchronous Event Listeners won't work because the method "console.log" is passed in as a event handler but the context 'console' is not bound to this handler/function.

This should be:

document.addEventListener("click", console.log.bind(console), false);

// Verified the issue on Chrome.

Sahil Budhiraja  Jun 01, 2013 
Other Digital Version 66
Callbacks and Scope

In my version of this (e-)book, the author wrote:

"If you call findNodes(myapp.paint), it won?t work as expected, because this.color will not be defined. The object this will refer to the global object because findNodes() is invoked as a function, not as a method. If findNodes() was defined as a method of an object called dom (like dom.findNodes()), then this inside of the callback would refer to dom instead of the expected myapp."

In my opinion, the argumentation is misleading. If findeNotes() is invoked as a method or invoked as a function is irrelevant for the this-value in the method myapp.paint() . In either case the this-value will be refer to the global object, because it is determined by the form of the invocation "callback(found)" (See http://dmitrysoshnikov.com/ecmascript/javascript-the-core/#this-value).

Anonymous  Feb 05, 2014 
Printed Page 74
init-time branching

This is not really an errata, but a suggestion for a new pattern, combining self-defining functions and init-time branching.

In stead of initialising the add- and removeListener() methods init-time, you could use the self-defining pattern to define those functions the first time they are called.
This way, they'd only be initialised when they're actually used, which is even more efficient than init-time branching.

Maybe the pattern should be called lazy initialisation?

Martijn Bak  Apr 22, 2011 
PDF Page 79
Final example

The example itself looks like this:

var alien = {
sayHi: function (who) {
return "Hello" + (who ? ", " + who : "") + "!";
};
}

alien.sayHi('world'); // "Hello, world!"
sayHi.apply(alien, ["humans"]); // "Hello, humans!"

One problem that I have with this is that the sayHi function shouldn't exist given the code directly preceding the example. I suppose you were referring to the earlier sayHi function separated by a lot. Not a big deal.

What was a little bit more confusing was that it is a little bit unclear in what you demonstrating. Are you saying that these two examples (other than the argument) are essentially identical? Will "this" be the same inside of them? I think that's what you mean by "When a function is a method of an object, there?s no null reference passed around (as in the previous example). Here the object becomes the first argument to apply()", but it might be a little more helpful if the examples used "this" in some way to demonstrate how the different applies work.

A minor complaint in an otherwise flawless book!

One other thing. Earlier in the page speaking about how to use apply you wrote, "the second is an array or arguments"

I believe it should say:
the second is an array of arguments

Hope these few suggestions help!

Jamund Ferguson  Dec 20, 2010 
Printed Page 79
1st example

The trailing exclamation mark is missing in the commented output where the function sayHi() is invoked for the first time. The output should be as follows:

...
// invoke a function
sayHi(); // "Hello!"
...

Justus Sturkenboom  Nov 26, 2012 
Printed Page 88
2nd paragraph

"Often developers use the convention of making the global variable APP CAPS, so it stands out to the readers of the code."

This is true for YAHOO/YUI, but I don't think this is "often" the case. Take a look at the list of registry candidates on openajax.org:

http://www.openajax.org/member/wiki/Registry_Candidates

Empirically, it is not common for library prefixes to be all caps.

Michael Bolin
Michael Bolin
 
Mar 17, 2011 
Printed Page 89
code snippets

"namespace" is allegedly a "potentially future reserved word" in JavaScript:

http://javascript.about.com/library/blreserved.htm

so it's probably not a good idea to recommend it as a property name, such as MYAPP.namespace.

Michael Bolin
Michael Bolin
 
Mar 17, 2011 
PDF Page 89
last code snippet

MYAPP.namespace = function(ns_string) {
var parts = ns_string.split('.'),
parent = MYAPP,
i;
// strip redundant leading global
if (parts[0] === "MYAPP") {
parts = parts.slice(1);
}
for (i = 0; i < parts.length; i += 1) {
// create a property if it doesn't exist
if (typeof parent[parts[i]] === "undefined") {
parent[parts[i]] = {};
parent = parent[parts[i]]; // THIS LINE WAS MISSING
}
}
return parent;
};

Hosam Shahin  May 24, 2014 
Printed Page 104
Code example under heading "Implementing the Constructor"

if (!modules || modules === '*') {

The above actually does not handle the star/asterisk (*) wildcard argument (the use case mentioned on page 102):

Sandbox('*', function (box) {
// console.log(box);
});

This is because at that point in the Sandbox() constructor, the modules variable will be an array, not a string. The resulting client code does not work; it ends up skipping the wildcard handling and instead looks for a property of Sandbox called '*' (star), which is likely undefined.

The simplest fix I can think of is:

if (!modules || modules === '*' || (modules[0] === '*')) {

Will Cain  Aug 12, 2011 
Printed Page 104
code after the first paragraph

modules = (args[0] && typeof args[0] === "string") ? args : args[0],

should be

modules = (args[0] && typeof args[0] === "string") && args[0] !=='*' ? args : args[0],

Songxun  Nov 13, 2013 
Printed Page 110
code sample

Is the prefix necessary? Shouldn't the use of hasOwnProperty take care of collisions with things like 'toString'?

Michael Bolin
Michael Bolin
 
Mar 17, 2011 
Printed Page 111
last code sample

I'm not sure if this is a great example of chaining:

document.getElementsByTagName('head')[0].appendChild(newnode);

Getter methods, like getElementsByTagName(), are expected to return a value, so there is nothing unique about chaining such methods. Mutator methods, such as appendChild(), are not always expected to, which is what I think you're trying to get at when talking about chaining.

Your obj.increment().add(3).shout() is a good example of this because those are three mutator methods put together. The DOM example doesn't seem as illustrative.

Michael Bolin
Michael Bolin
 
Mar 17, 2011 
Printed Page 127
second code example

In this Holy Grail example, shouldn't the Child still call Parent's constructor method:

function Child() {
Parent.apply(this.arguments);
}
inherit(Child, Parent);

This is at least how things are done in the Closure Library.

Michael Bolin
Michael Bolin
 
Mar 17, 2011 
Printed Page 129
last code sample

The beginning of this expression:

if (Child.uber

can Child.uber ever be false in a boolean context? It seems like it should not be possible because of how it is defined:

Child.uber = Parent.prototype

I suppose you would have to do something pretty strange like:

var obj = {};
obj.__proto__ = null;

klass(obj, props);

maybe?

Michael Bolin
Michael Bolin
 
Mar 17, 2011 
Printed Page 129
Code snippet

Although "inheritance" at more than one level is not explicitly discussed in this section, it seems that it is not correctly managed by the klass function.

Let's say we defined another "class" like so:

var UltraMan = klass(SuperMan, {
__construct: function (what) {
console.log("UltraMan's constructor");
},
getName: function () {
var say = UltraMan.uber.getName.call(this);
return "Tada! " + say;
}
});

and we defined the following object,
var ul = new UltraMan('Urutoraman');
we can notice that Man's constructor is not called.

This is apparently because the __construct property is not recursively called for the ancestral "classes". It is just called for the immediate Parent.

A quick and dirty fix would be to change the definition of Child (inside the klass function) like so:

Child = function () {
// Don't call ctor if Parent is Object! (tail condition)
if (Child.uber !== Object.prototype) {
Child.uber.constructor.apply(this, arguments);
}

if (Child.prototype.hasOwnProperty("__construct")) {
Child.prototype.__construct.apply(this, arguments);
}
};

The tail condition of the recursion is managed when we reach the Object constructor, which does not have any "__construct" property.

Erwin Schaefer  Jul 24, 2012 
Printed Page 130
1st paragraph, list item 2.

The sentence states that there might be cases when "uber" is not defined. However, Parent is set to Object if the "class" being defined does not explicitly "inherit" from anything (that is, if it implicitly "inherits" from Object).
Thus, Child.uber is set to Object.prototype, and uber is defined.

As a check:
In a node.js console, after copy/paste of the code, the following statements evaluate to true:
Man.uber === Object.prototype
or
Man.uber.constructor === Object

Erwin Schaefer  Jul 24, 2012 
Printed Page 145
function Universe() {...} code

The Universe function for the implementation of the singleton pattern on page 145 has minor issues:

When we execute:

Universe.prototype.nothing = true;
var uni = new Universe();

then, Universe.prototype no longer has "nothing" as an own property.
Universe.prototype is actually changing after the first invocation of the constructor.
The original prototype can be reached with uni.__proto__.__proto__ (the new prototype is reached with uni.__proto__). This adds a lookup stage for prototype properties or methods.

Moreover, the singleton object uni is polluted with "constructor" as an own property ("constructor" property usually belongs to the prototype).

The following implementation solves these issues (and hopefully does not bring new issues!)

function Universe() {
var instance;

var backup = Universe.prototype;

Universe = function Universe() {
return instance;
}

Universe.prototype = backup;
Universe.prototype.constructor = Universe;

instance = this;
instance.start_time = 0;
instance.bang = "Big";

return instance;
}

Erwin Schaefer  Jul 24, 2012 
Printed Page 153
2nd code sample

I'm not sure this is a valid example of the decorator pattern because in some examples, the contract of getPrice() is that it returns a string, and in other cases, it returns a number. I thought that a decorator should maintain the original API and that it should be transparent to the user. In this case, because of the changes in the API, the order in which the decorators are applied are particularly important, so there is no such transparency.

Michael Bolin
Michael Bolin
 
Mar 17, 2011