Susan Harkins (406) [Avatar] Offline
#1
Please post errors in the published version of Secrets of the JavaScript Ninja, Second Edition here. We'll publish a comprehensive list for everyone's convenience. Thank you!

Susan Harkins
Errata Editor
420265 (3) [Avatar] Offline
#2
Please check out this one

https://forums.manning.com/posts/list/38489.page

This error both in the exercise of chapter 3(page 60) and Appendix C Exercise answers(page 413)
johnkorz (4) [Avatar] Offline
#3
Oops! Funny coincidence. Post right above this one is the same error.

Another possible one: https://forums.manning.com/posts/list/39201.page
236120 (1) [Avatar] Offline
#4
There's a subtle error on the page 359:

outerContainer.addEventListener("click", function(event){
report("innerContainer handler");
assert(this === outerContainer,
"This refers to the outerContainer");
assert(event.target === innerContainer,
"event.target refers to the innerContainer");
});


should be

outerContainer.addEventListener("click", function(event){
report("outerContainer handler");
assert(this === outerContainer,
"This refers to the outerContainer");
assert(event.target === innerContainer,
"event.target refers to the innerContainer");
});
2261 (1) [Avatar] Offline
#5
Listing 3.3 will incorrectly classify 0 as a prime number.
johnkorz (4) [Avatar] Offline
#6
9.5 Exercises

Question 4:

const first = persons.map(ninja => ninja.age);

Should be...
const first = ninjas.map(ninja => ninja.age);


Question 7:
The last assertion should fail. "Hattori" was never added to the set nor was it initialized.
241522 (2) [Avatar] Offline
#7
delete
405599 (4) [Avatar] Offline
#8
In Listing 8.7 code return error
TypeError: proxy set handler returned false for property '"nickname"'
after line
representative.nickname = 'Tenno';
405599 (4) [Avatar] Offline
#9
405599 wrote:In Listing 8.7 code return error
TypeError: proxy set handler returned false for property '"nickname"' after
representative.nickname = 'Tenno';
437938 (1) [Avatar] Offline
#10
3.6 Exercises - 5
should be return ninja + " " + action;

instead of

return ninja + " " + katana;
435657 (4) [Avatar] Offline
#11
There's a discrepancy between the code in 6.6 Exercises Q3 and the end of chapters exercises, the final line calls the iterations next with 4 as the arg but in the answers in the back, it's called with 5 as an arg

let a2 = generator.next(4).value <--- in the chapter
let a2 = generator.next(5).value <--- in the exercise answers
SteveS (10) [Avatar] Offline
#12
Table 10.1: Incorrect description for dot metacharacter

The Matches column for Predefined term . states that it matches "any character, except for whitespace characters (\s)". I believe the only whitespace characters the dot metacharacter will not match are line break characters (see MDN). A better description would be "any character, except for line break characters (\n, \r, \u2028, and \u2029)".
436710 (1) [Avatar] Offline
#13
Surely some duplicates to already mentioned points, but these are the notes I took:

- Often there is a reference to "Appendix C", regarding debugging tools or the "assert-function".
I found these things in "Appendix B".

- On page 151 is a reference the appendix C where the function "report" can be found. At least I did not found it neither in appendix B nor appendix C

- On page 235, it is not an error but I just wondered about the "var" in "var allNinjasAreNamed...".
It is more a thing of personal perception. But as I could not find a reason for the "var" it felt a somewhat inconsistent to the rest (even it is explicitly written "[...]almost always use const and let instead of var." p. 113).

- On page 159, could it be that there is missing a closing bracket? ("(res => handle(iterator.next(res)))"

- This is now a point I was thinking about writing it down because it comes very close to bean counting and I am not sure whether I misunderstood the explained concept... But as I do not know whether it is important to you, I decided to let you know that I was thinking about the sentence "[...], we can send data into a generator by passing [...]". But do I pass it to the generator or to the iterator which is returned by the generator. I am rather unsure about this point.

- On page 142, the arrow for the "suspended state" points to the "completed state".
- On page 144, the arrow for the "executing state" points to the "suspended state".

- On page 419 is written "5: passing in 5 [...]". According to the exercise from page 163 the argument is 4. And so on p. 419 it should be "let a2 = generator.next(4).value;" and the return value is also 4.


Kind regards
Niklas

240548 (1) [Avatar] Offline
#14
Discrepancy: Page 425

The answer states the correct final result, however the description of the statements uses a form of splice() that is not expressed, and omits mention of the final samurai.pop() method. According to the code it states samurai.splice(1, 0, "Hattori", "Takeda") on the computed samurai array value of ["Tomoe", "Oda"] would yield ["Tomoe", "Hattori", "Takeda"]; however this is not true. Only after running the samurai.pop() statement does this become true; the current description suggests that perhaps an earlier draft of the book used splice(1,1, ...), without the samurai.pop(), which would of course delete element 1 and insert items as indicated.

Suggested replacement for paragraph "A."

The value of samurai is ["Tomoe", "Hattori", "Takeda"]. The array starts empty; push adds Oda to the end, and unshift adds Tomoe to the beginning; splice here does not remove any items, but inserts Hattori and Takeda starting at index 1 (after Tomoe), and the final pop method removes Oda from the end of the Array.

----

FYI for consistency with the rest of the book, "Hattor" should read "Hattori" and this text appears truncated in Chapter 9 exercise 4 and answer 4 (pages 257 and 425 respectively).


Sabuncu (34) [Avatar] Offline
#15
P. 14, section 2.1, "The lifecycle overview", paragraph 1, is missing a circular indicator that would link the text to the corresponding user action in Figure 2.1 that says "Enters URL (or clicks link)", similar to those in the following paragraph on the next page:
image
Sabuncu (34) [Avatar] Offline
#16
The example involving Listing 2.3 on p. 26 is misleading. In the paragraph starting with "Adding functions to...", the text indicates that using the addEventListener() method is the preferred approach to add event-handlers because it "enables us to register as many event-handler functions as we need." However, the code in the listing registers handlers for two separate events (mouse move and mouse click), not the same event.

So, while the code in the listing is not incorrect, it is not an illustration of registering multiple handlers for the same event.

In any case, registering multiple handlers for a single event is an advanced topic that should best be left to later chapters of the book.
Sabuncu (34) [Avatar] Offline
#17
Suggestion for Listing 3.2:

I suggest that the listing be modified so that the second assert call shows a fail, as follows:
assert(store.add(ninja), "Function added.");
assert(store.add(ninja), "Function added.");

Result:
image
I believe showing an actual fail as a fail is more effective here.
Sabuncu (34) [Avatar] Offline
#18
On p. 52, in the last paragraph of the section, it says "Arrow functions, like all other functions, can receive arguments in order to use them to perform their task." This is confusing because of a redundancy here, as the previous example two paragraphs above on the same page already involved an example of just such a function (greet()) that received an argument (name).

This can be remedied if the sentence in question is modified as follows:

"To recap our discussion, arrow functions, like all other functions, can receive arguments in order to use them to perform their task, as we have seen in the example above."
Sabuncu (34) [Avatar] Offline
#19
On p. 56, in Listing 3.8, the highlighted wording is not clear:

image

What is "the first function" (only one function is shown), and what is "the body statement" (there are two statements in the body of the function)?

The action parameter will be undefined for each call of the function except for Yagyu.
Sabuncu (34) [Avatar] Offline
#20
On p. 58, in the first paragraph, it says: "... this doesn't enhance code readability and should be avoided...". This statement seems to be about the use of the technique shown in Listing 3.10 (i.e. using previous default parameters later in the list). However, because of the following sentence ("But moderate use of default parameters..."), the intended meaning is left unclear and confusing.
Sabuncu (34) [Avatar] Offline
#21
On p. 65, the first sentence of the section titled "ARGUMENTS OBJECT AS AN ALIAS TO FUNCTION PARAMETERS", it says "The arguments parameter has one curious feature: It aliases function parameters."

Rather than being a curiousity, this feature (i.e. aliasing) would be expected of a language/runtime that acts consistently. It would only be worth noting if this feature did not work as such.

UPDATE:

Or, an example should be given for those cases where aliasing would be dangerous.
Sabuncu (34) [Avatar] Offline
#22
Suggestion for Chapter 4:

Examples are provided in the first half of p. 68 for various types of function calls. Without explanations yet of how they work, these examples are not useful and just take up space. These examples should be removed and instead, the discussion should flow immediately to 4.2.1 where the text picks up explaining the four types of invocation.
Sabuncu (34) [Avatar] Offline
#23
On p. 68, functions in examples are shown in an abbreviated form as follows, apparently for sake of simplicity:
function ninja(){};

This should be noted somewhere, indicating that "the body of the function has been omitted for simplicity."
Sabuncu (34) [Avatar] Offline
#24
On p. 70, the verbose descriptions output by the assert statements in Listing 4.6 make it difficult to tie the results with the statements that produce them.

Suggestion: In the assert text, output the actual code that was used with that assert call, as follows:

Instead of the following:
assert(getMyThis() === window, "Another function call in window");

Do this:
assert(getMyThis() === window, "getMyThis(): this === window");

This is how I changed the output:

image

An additional note: For a seasoned software engineer who knows C++ and C#, and is trying to master JavaScript, the ninja theme gets old pretty fast. It would be better to treat the reader as a professional. (The ninja title can be kept to indicate that the book is for those who are aspiring to learn the advanced features of the language.)
Sabuncu (34) [Avatar] Offline
#25
Figure 4.1 on p. 73 does not match the corresponding explanation in the numbered list above. Specifically:

- Item in the figure actually corresponds to item number in the numbered list.
- Item in the figure does not have a corresponding explanation in the numbered list.

Also:

- The initial empty object shown on the lower left should not have a "ninja" stamp on it, as it is initially a pure empty object. It gets a type as a "Ninja" (with initial letter uppercase) after the construction is over, and that object is shown in the lower right.
- The arrow heading out of the unnamed function should really start from the return statement, as shown with the red line in the redacted figure below.

image
Sabuncu (34) [Avatar] Offline
#26
The section titled "THE SUPERPOWERS OF CONSTRUCTORS" on p. 71 is completely muddled. The section starts with an explanation of Listing 4.7, describes Figure 4.1, then on p. 74, it goes back to describing Listing 4.7 all over again, as if the Ninja constructor has not been discussed at all in the past couple pages.
Sabuncu (34) [Avatar] Offline
#27
The voice used (third person) in the descriptions within Listing 4.9 on p. 75 is misleading. For example, the topmost description (upper-right corner) says "Creates our own object with a known property". Who does the creation? The top-level global script. So, a better approach and wording would say "Create global object with known property".

Similarly, the next description in the listing is also poorly worded: "Returns that object (which object?) despite initializing the object passed as this" A better wording would be: "The constructor,
despite initializing the object passed to it through "this", returns a global object created elsewhere
"

Also, the sentence immediately following the listing says "This listing takes a slightly different approach. We start by creating a puppet object with the property rules set to false:", which again is misleading. The object created is not a "puppet" object. It is some object with a property called "rules" that is then assigned to the variable "puppet".

On the following page (p. 76), the sentence in the middle of the page says "It turns out that our tests indicate that the puppet object is returned as the value of constructor invocation, and that the initialization that we performed on the function context in the constructor was all for naught." This is not entirely true. The initialization performed still plays a critical role in the example, in the following statement:
assert(emperor.rules === false,
    "The puppet does not know how to rule!");

Although the Emperor() constructor did not perform any initialization, the base object created for the "emperor" variable still has a "rules" property; otherwise, "emperor.rules" would have been "undefined". The false value for "rules" set when the global object was first created survives, and is exposed in the above statement.
Sabuncu (34) [Avatar] Offline
#28
On p. 76, the following section makes no sense at all:

image

The reference in the second bullet item to "nonobject" is the only one in the entire book, and it is not defined or explained. What is a nonobject? How does it correspond to the example that was just covered? I feel this bullet item needs to be completely re-written so that the intended meaning can come across.

The first bullet item can also be made clearer if it is expanded as follows:

     If the constructor returns an object, that object is returned as the value of the whole new expression,
     and the newly constructed object passed as this to the constructor is discarded [in our earlier example,
     the object with the "rules" property that was set to true in the Empire() constructor]

Sabuncu (34) [Avatar] Offline
#29
On p. 76, the first code example given in the section titled "CODING CONSIDERATIONS FOR CONSTRUCTORS" is so contrived that the reader can no longer fathom the educational intention behind the example. Why would one do what's described in the example? Is there any useful purpose? If not, why should the reader follow the text?

Furthermore, the first paragraph in the aforementioned section says:

The intent of constructors is to initialize the new object that will be created by the function invocation to initial conditions. And although such functions can be called as “normal” functions, or even assigned to object properties in order to be invoked as methods, they’re generally not useful as such. For example

The grammar of the first sentence is really poor. And in the second sentence, what is meant by a "normal" function? Again, if what is discussed is not useful, why even discuss it, especially at such an early stage in the book?

(I feel the book is starting to fall apart at this point - but I am determined to go on!)
Sabuncu (34) [Avatar] Offline
#30
On p. 80, in the second paragraph:

In the case of apply, we use an array of arguments, and in the case of call, we list them as call arguments, after the function context.

The bold section should be: "we specify a list of distinct arguments"
Sabuncu (34) [Avatar] Offline
#31
On p. 78, the concept of a "backing object" is mentioned twice but is not defined. Yet, on p. 96, the related topics of accessors and getters are described (albeit in limited fashion). It might help some readers to also describe backing objects, if at least for the sake of consistency.
Sabuncu (34) [Avatar] Offline
#32
In Listing 5.6 (starts on p. 107) a const variable is created on the fly and a new property is added:
const secondConst = {};
secondConst.weapon = "wakizashi";

HOWEVER, the new property can be changed! I tested the following in Chrome Version 55.0.2883.87 m on Windows 7, and the value of the weapon property was changed, even though it's part of a const variable:
secondConst.weapon = "new value";
assert(secondConst.weapon === "new value", "new value set for secondConst.weapon");

The same holds true for the value pushed to array thirdConst; it can be changed.
thirdConst[0] = "new value";
assert(thirdConst[0] === "new value", "new value set for thirdConst[0]");
In light of the above facts, I think section 5.5.1 should be changed to clarify how const variables work, and the example in the listing should be augmented.
Sabuncu (34) [Avatar] Offline
#33
On p. 111, it says:

"Because this behavior is a bit strange, the ES6 version of JavaScript offers two new variable declaration keywords: let and const."

This was already mentioned earlier on p. 106, in the note at the bottom of the page.
384686 (11) [Avatar] Offline
#34
12.1 Injecting HTML into the DOM

There appears to be a paragraph missing on p. 307

We're shown how to inject HTML into the DOM using 1 line of jQuery, then asked to compare it with a long-winded DOM API only approach.

image

The reasons for not using jQuery are not explained. We jump immediately to a plan of how we'll implement a more efficient way of injecting HTML without jQuery.
458279 (1) [Avatar] Offline
#35
Section 10.8. Exercises, page 281, question 12.

The regular expression literal is incorrect. The square brackets are missing.

in the book: /0-5/g

should be: /[0-5]/g

You'll find the same mistake in the answer to this question on page 427
Levon (1) [Avatar] Offline
#36
Is there a PDF document with all of the errata in an organized manner? E.g., by pages or chapters. This is not the best way to help readers looking for a way to identify potential errors in the text.

Better yet, is there a 2nd printing coming with the errors fixed? The book gets great reviews, but there are many complaints about typos/errors. I hesitate buying (or recommending) this book with just this webpage listing to address the errors.

Thanks.
Susan Harkins (406) [Avatar] Offline
#37
At this time, there is no comprehensive errata list.

Susan Harkins
Errata Editor
alfred3x (6) [Avatar] Offline
#38
So, why are we spending (wasting?) our time sending in corrections if they're not going to be used?
Susan Harkins (406) [Avatar] Offline
#39
They are being used! Every reader who pursues this thread benefits. Thanks to everyone for sharing what you've found!

Susan Harkins
Errata Editor
alfred3x (6) [Avatar] Offline
#40
Thanks for the quick reply, Susan.

It would be more useful to have a list of errata sorted by page.

Conceivably, this could even be created using a plugin right in the forum.

It would also be useful to have a link to the errata from the user's bookshelf page.
Susan Harkins (406) [Avatar] Offline
#41
We rely on the authors for such a list. Often, they are so busy writing the next edition or a new fabulous book that we try not to bother them too much. It's a trade-off. We really do appreciate these threads -- they are a great benefit.

Susan H.
Inner-self (8) [Avatar] Offline
#42
If (from pg 52):

"A parameter is a variable that we list as part of a function definition."
"An argument is a value that we pass to the function when we invoke it."

then:

the term argument appears to be incorrectly used here, instead of the term parameter.

"By prefixing the last-named argument of a function with an ellipsis (...), we turn it into an array called the rest parameters, which contains the remaining passed-in arguments." (pg 54)





Additionally, I think the publisher should be responsible for compiling the errata list as a page indexed summary. Anything less is customer negligence.

At least make a well-formatted errata list indexed by page number; and put somebody in charge of curating it. That's publishing!

And invest and pay for hella-better editing, too! Think of editing as an investment toward lowering costs that may also have the positive side-effect of building a good or better reputation for the Manning company.

The suggestion that the authors should perform information management of errata data is unrealistic, offensive and tone deaf. I thought the content was OWNED by the publisher in most cases via a contract terms and agreement with the author.

Improved editing could reduce the volume of errors; making it less work to maintain an errata list. I hope I did not blow any minds with this idea. If so I am sorry. Considering how little money an author is paid for the volume of work it takes to write technical material, asking the authors to do it, is tone deaf. And it is offensive to everybody when the publishing business - being a 24x7 business thing - would not be stepping up to support both the authors and also your end customers, too.

I believe, specifically, that providing as little support for a book product's list of errata, as is done here at Manning with a "self-service" thread in a web forum (dedicated as a free form errata) is a pathetic way to provide a critical post-sale technical book support service. It may also be offensive to many of your stakeholders and customers. It's 2017 already, not 1997.

For example, if a customer wanted to look up a detail in this book's errata, the last thing they would want to do is wade through a series of User commentary, like mine.

Be better, Manning. Please...

alfred3x (6) [Avatar] Offline
#43
Wow! Perfectly articulated @inner-self!

I would add that it doesn't have to be a labor intensive task. If they simply added a couple of extra fields, such as page # and errata yes/no, the list would sort itself!

Very, very short sighted, Manning! And terribly frustrating for the reader.
Susan Harkins (406) [Avatar] Offline
#44
Thank you for your comments regarding our errata collection and reporting process. Because a book is the author's intellectual property, we hesitate to make corrections about code and logical discussions without the author's permission. Not every errata post from a reader is valid. Nor do editors have the technical expertise to make such decisions. It's a problem we are trying to solve.

I have canvassed for a more flexible reporting process at the forum level, and I'm hopeful if implemented, it will resolve most of these issues. We appreciate your comments, and although we don't have a great solution for you right now, we are working on it. Thank you for your patience, and if you have an idea you think might improve things, I hope you'll let me know.

Thank you,
Susan Harkins
Errata Editor
Inner-self (8) [Avatar] Offline
#45
Hi Everybody!

Now, Is everybody at Manning sitting down and wearing their protective goggles?

I'm gonna blow some minds again, and I take no responsibility for any damages or what you may see here:

Example of Technical Book Errata Formatted for End Customers, found on the Dark Web of the Internet.

A creative team may find ways to improve on this, though it does seem to meet some essential requirements.
Note the accommodation for confirmed and unconfirmed errata.

HTH! Manning management fund the right thing!
Susan Harkins (406) [Avatar] Offline
#46
BTW, this book does have an errata list -- return the book's home page and click the Errata link to the left. This list is verified by the authors. The discussion is valid as not all books have a list and the forum could be more flexible in this regards. My apologies for not listing the link sooner. For future reference, if a book has an errata list, you can always access it by the Errata link on the book's home page.

<https://www.manning.com/books/secrets-of-the-javascript-ninja-second-edition>

Susan H.
Inner-self (8) [Avatar] Offline
#47
Thank you very much. The is definitely better than sorting through the thread.
546110 (1) [Avatar] Offline
#48
Chapter 9 - question 3:
The result is correct, but the explanation is completely wrong.
the code:
const samurai = [];
samurai.push('oda');
samurai.unshift('tomoe');
samurai.splice(1,0,"hatory",'takada');
samurai.pop();


The result is indeed ["tomoe, "hatory", "takada"] but it's not because of the splice() as the answer explains, it's because of the pop(). The splice just added in index 1, and the pop takes 'oda' out.

565212 (1) [Avatar] Offline
#49
The solution for Chapter 10 exercise 11 appears to be incorrect.

/(?:ninja)-(trick)?-\1/
should not match
"ninja-"
because the expression expects another
"-"
before the backreference. The expression would, however, match
"ninja--"
Louis Lazaris (2) [Avatar] Offline
#50
In Chapter 12, section 12.3.1, it says "It should be noted that any values in an element's style property take precedence over anything inherited by a style sheet (even if the style sheet rule uses the !important annotation).

The same statement is made in 12.3.3:

"Styles specified by an element's style attribute always take precedence over inherited styles, even if marked !important."

However, this is not true. Anything marked with "!important" will take precedence over a style added via JavaScript's style property or via the style attribute in the HTML.

Here is a demo:

https://jsbin.com/nedewiw/edit?html,css,js,output

Notice the background color is defined in three different ways, but the !important declaration takes precedence over the others.
Louis Lazaris (2) [Avatar] Offline
#51
In chapter 12, section 12.3.5 it suggests a way to measure the height and width of an element that's set to "display: none". It gives multiple steps: Convert to display:block, set visibility to hidden, set position to absolute, grab the dimensions, then restore the properties.

But this is a really fragile and harmful way to do this. When you change an element from "position:static" (the default) to "position:absolute", you're making a major change to the way the element is laid out on the page, which has the potential to affect its dimensions.

Here's an example demo:

https://jsbin.com/hanojek/edit?html,css,js,console,output

Notice the dimensions of the element are different before and after "position:absolute" is applied. This is because absolute positioning takes the element out of the normal flow, which (in part) means it won't expand to fill its container (as it does when set to static positioning).

But this is just one problem with this technique. There's also the possibility that the element in question is not supposed to be a "block" element. For example, it could be a flex container, or an inline element, or even a table element. Setting such an element to "display: block" could potentially have undesired side effects. In most cases, this technique would probably work, but there are many instances (such as my demo above) where the result would not be desirable.