JavaScript: The Definitive Guide, Fifth Edition by David Flanagan The unconfirmed error reports are from readers. They have not yet been approved or disproved by the author or editor and represent solely the opinion of the reader. Here's a key to the markup: [page-number]: serious technical mistake {page-number}: minor technical mistake : important language/formatting problem (page-number): language change or minor formatting problem ?page-number?: reader question or request for clarification This page was updated July 9, 2008. UNCONFIRMED errors and comments from readers: (36) 3.6.1; "var a = new Array(10); creates a new array with 10 undefined elements. " Would that not be 11 elements? {49} Section 4.1, safari; In Java 1.5 with autoboxing the following code is legal, Object o = null; o = 10; o = "hey"; Autoboxing is overlooked in section 4.1, Variable Typing [52] 4.3.1 No Block Scope, 2nd paragraph and concept in general; The second code example that follows "The rule that all variables declared... can cause surprising results. The following code illustrates this:" var scope = "global"; function f() { alert(scope); // Displays "undefined", not "global" ... } f(); --------------------- This code does in fact display the word "global" in an alert window (IE7, FF2). It seems to me that if you couldn't reference variables outside functions by name you wouldn't actually have 'global' variables...? [52] At the bottom of the page; There is in fact NO ERROR in the last code segment on page 52 even though the "Unconfirmed error reports and comments from readers" shows that someone has claimed otherwise. I've tested the example as given in the book and the behaviour exactly matches the one indicated in the code comments and the description around the example code. (54) 3rd paragraph from bottom of page, last sentence; "there just happens to be two references to it." Change "happens" to "happen" {65} 1st full paragraph; [ For example, the following code sets both i and j to 2: i = 1; j = ++i; But these lines set i to 2 and j to 1: i = 1; j = i++; ] No, the first two lines set i to 1 and j to 2. The second two lines set both i and j to 1. [65,140] upper half; I've been checking the page "Unconfirmed error reports and comments from readers". Apart from the one remark I sent earlier here are my other findings: The errata claims that the text on the page 65 of the book: For example, the following code sets both i and j to 2: i = 1; j = ++i; But these lines set i to 2 and j to 1: i = 1; j = i++; is in error. It isn't. Instead it correctly describes how these expressions behave. The behavior is the same in C/C++, Java, JavaScript and I'm sure in some other languages too. {114} para 6; line: var undefs = [,,]; .... comment should say "An array with 3 elements, all undefined" (120) first paragraph under "7.7.6 splice"; This paragraph states that splice() does not return a new array because it modifies the array in place. Actually, the both the examples below (on p. 120) and the Core JavaScript Reference entry for splice() show that splice does return a new array, as well as updating the array in place. The language used is confusing. It should indicate that the array you receive, if any, contains the removed elements, not the newly spliced array. {140} Example 8-3; In the function copyUndefinedProperties(), "if (!p in to)" is used to check whether the object "to" lacks property "p". Since the unary ! operator has a higher precendence than the "in" operator (see Table 5-1, pp. 60-61), this statement is incorrect: p is first negated to obtain !p, and then it is checked whether !p is a property of to. Parentheses are needed: "if (!(p in to))". {140} first whole function (copyUndefinedProperties); Because the ! operator has higher precedence than the in operator, the function just checks to see if "false" is in the to object for each property in the from object. Function should be: function cu(from, to) { for(p in from) { if (!(p in to)) to[p] = from[p]; // parentheses around 'p in to' } } (141) code just before section 8.8; The code could be fleshed out a bit more to illustrate the idea that 'this' is a keyword never bound to any particular call object. Yes, that info is on p 137 at the end of 8.4, but by this page that info is a bit fuzzy and still abstract. Perhaps all of example 8-5 needs to be in section 8.8.4.1. function makePropertiesInThis ( arg1, arg2, arg3 ) { for ( var i=0; i < arguments.length; i++ ) { this[ 'js' + i ] = arguments[i]; } return this; } o = {}; o.func = bindArguments( makePropertiesInThis, 'foo', 'bar' ); x = o.func( 'baz' ); // print is defined as earlier in the book print( x === o ); // true print( x === this ); // false print( "js0" in o ); // true, foo print( "js1" in o ); // true, bar print( "js2" in o ); // true, baz print( "js0" in this ); // false print( "js1" in this ); // false print( "js2" in this ); // false x = (bindArguments(makePropertiesInThis, 'apple'))('banana','cherry'); print( x === o ); // false print( x === this ); // true print( "js0" in this ); // true, apple print( "js1" in this ); // true, banana print( "js2" in this ); // true, cherry (143) first sentence; The correction at http://www.oreilly.com/catalog/9780596101992/errata/jscript5.807 is incorrect; the sentence was correct before. The overall structure of the sentence is "The facts...interact". The sentence is describing three facts which interact. So it should be "facts" and not "fact". (145) Example 8-6; In Example 8-6, the "get" and "set" methods are defined, but their comments have their names confused ("getter" and "setter" should be switched). The text reads: // The setter method simply returns the value. o["get" + name] = function() { return value; }; // The getter method stores the value or throws an exception if // the predicate rejects the value. o["set" + name] = function(v) { if (predicate && !predicate(v)) {157 (4th ed.)} last paragraph (4th ed).; In Section 10.2, page 157, 4th ed., there is an example for parsing a URL using String.match(). In the last paragraph there is an off-by-one error in the description of the index property of the result: AS IS: "So, in the previous code, the value of the result.index property would be 21, since the matched URL begins at character position 21 in the text." SHOULD BE: "So, in the previous code, the value of the result.index property would be 22, since the matched URL begins at character position 22 in the text." {158} first paragraph; "When you use JavaScript objects to *simulate* object-oriented programming techniques ..." [emphasis added] maybe should be something like: "When you use JavaScript objects to simulate the object-oriented programming techniques of strictly-typed languages ... " On page 157: "JavaScript is a true object-oriented language." If that's true, we shouldn't need to simulate object-oriented programming techniques. If we do need to simulate them, then JavaScript must not be a true object-oriented language. [161] 3rd paragraph (the creation of an 'instance method'); INSTANCE/CLASS METHOD CONFUSION (5th Addition Rhino Book) The definition of Circle.prototype.area = function() { etc.... } is described as an instance method, which would be a function which is present in all instances of a Circle, but could POTENTIALLY be changed without affecting other instances. eg. for these two objects - var a = new Circle(2); var b = new Circle(6); // I could do this..... b.area = function() { return 1; } I could redefine the 'area' function for 'a' but it would NOT be changed for 'b' surely? However, by defining the 'area' function as part of the prototype, that would change the function for ALL Circle instances. Therefore it is a CLASS method, not an INSTANCE method. 'area' should be defined in the constructor, just like INSTANCE PROPERTIES are. function Circle(radius) { this.r = radius; this.area = function() { return (Circle.PI * this.r * this.r); } } // and something more likely used for a class function using prototype, like: Circle.prototype.getNumberOfSides() { return 1; } (although, Circle.getNumberOfSides() is an infinitely better way!) I find the sections from 9.3.1 - 9.3.5 very confusing to read as an experienced C++ developer, as there seems to be some fuzziness in the thinking here. Also in 9.3.2.1 you say the same thing, that an instance method can be defined via the prototype, but this is just plain wrong! ps. I am using the latest firefox, so I hope it's not a bug in it's interpreter! Page 161: The comment says that 9.3 is very confusing and in fact partly wrong. It isn't. Flanagan is just telling how things are done in JavaScript. [166] last paragraph; the "new" operator doesn't belong there. here's the output from jslint: Error: Problem at line 1 character 21: Weird construction. Delete 'new'. complexNumbers.sort(new function(a,b) { return a.compareTo(b); }); Problem at line 1 character 65: Missing '()' invoking a constructor. complexNumbers.sort(new function(a,b) { return a.compareTo(b); }); Members Occurrences compareTo 1 sort 1 {166} last line; Remove the 'new' keyword. (170) sections 9.5.1 and 9.5.2; The implementation provided for simulating "super" (via the "superclass" property) does not work when more levels of class hierarchy are used than shown. For example, if Class C extends B, and Class B extends A, then when the constructor B referenced "this.superclass" (expecting a reference to "A"), it would instead get "B" because the "this.superclass" defined by C would have overridden/obscured it. (176) Footnote in section 9.7.3; The footnote begins: 'The term "duck typing" has been popularlized' 'popularlized' should be 'popularized' (203) end of page; The following statement confuses some readers (including me at first): "The non greedy version of our pattern does match at the first character of the string, so this match is returned; matches at subsequent characters are never even considered". The "does match at the first character... so this match is returned" induces people to think "the match is the first character?". I suggest the following formulation: -- The non greedy version of our pattern does match starting from the first character of the string, so the complete match is the one retained; matches starting at subsequent characters are never even considered after the first one. In other words, the match is "leftmost" ("leftmost longest" for greedy, or "leftmost shortest" for non-greedy, but always "leftmost"!). -- (I borrowed the "leftmost" concept from "Programming Perl".) [203] Below Table 11-3 in Chapter 11; Regarding regular expressions, the following text: /\w{3}\d?/ // Match exactly three word characters and an optional digit is incorrect. This regular expression will match 'AAA3' like it is supposed to. But it will also match 'AAAA3'. Since there are four A's, this regular expression does not "match exactly three word characters and an optional digit." Page 203 (regular expressions): This states that the text in the book: "/\w{3}\d?/ // Match exactly three word characters and an optional digit" is incorrect while it isn't. Maybe the wording isn't clear in the original comment. I'm not capable of discussing that because I'm not a native speaker of English. But the claim that the comment is wrong because of the fact that the regexp matches "AAAA3" i.e. 4 letters followed by a digit is clearly wrong. The regexp produces a match but that match does not match the whole of the string "AAAA3" it only matches the first 3 letters. This can clearly be seen with the following code that uses different letters instead of A's only: y = "ABCD3".match(/\w{3}\d?/); alert(y); // shows ABC y = "ABC3D".match(/\w{3}\d?/); alert(y); // shows ABC3 {204} 3rd paragraph, 4th sentence; It looks like there's an extra closing parentheses in "/(ab|cd)+|ef)/" (218) 2nd bullet in section 12.1.1; The pattern in the bullets is Java -> JavaScript but the second bullet reads: * All java.lang.Number objects convert to Java numbers. I believe it should read: * All java.lang.Number objects convert to JavaScript numbers. (232) 2nd; I cannot get the example 14-1 and 14-2 to work. I am using IE7 and checked line by line. Could there be a problem in the code? {275} 4th paragraph, explanation of viewport (also innerwidth/innerheight p 913); your definition of 'viewport' is (as it should be) the window minus menus, scrollbars, etc. your code works as advertised in the browsers OmniWeb and Safari on MacOS X Leopard. with the browsers Camino, Firefox, Mozilla, Navigator, SeaMonkey (all on MacOS X) and Internet Explorer 7 (on Win XP) your code returns the width of a frame including the scrollbar. Specifically on Safari, the proper width is the 'computed style width' of the body; however, this value appears to be 'auto' in the other browsers. [276] Also first "if" statement on page.; If not an error, this is something that should be pointed out to the reader... if(window.screenLeft) evaluates to FALSE, even with IE, if the value of screenLeft is zero. So using this code with a window that opens full-screen, for example, results in an undefined function error. (276) line 60 in the file js5examples/14/Geometry.js in ; the book correctly says if (document.documentElement && document.documentElement.scrollWidth) { but the file contains if (document.documentElement && document.documentElemnet.scrollWidth) { (276) Your sole listing here is wrong: http://oreilly.com/catalog/9780596101992/errata/9780596101992.907 It is correct the way it is printed, not with the "=== undefined" added. (277) line 60 of provided file 14/Geometry.js; The book is correct, but the code provided has a typo in line 60: if (document.documentElement && document.documentElemnet.scrollWidth) { the second documentElement is misspelled. (291) last paragraph; In the 3rd line from the bottom of page 291 there is the code line Window.open() instead of window.open() All through this chapter 14 which I am currently reading, I find the expression "the Window object" ("window" with capital W and in Roman) where I would have expected to see "the window object" (that is "window" written with small w and in Constant Width). (323) First comment section of code; The line that says * element is looked up using getElementsById() should say * element is looked up using getElementById() There is no getElementsById() method. {332} fifth line of code; Example 15-9 table.appendChild(row); is not a good idea for Internet Explorer -- wants rows appended to tbody (or thead or tfoot) Firefox and Safari happy as clams I notice the screen shot (Figure 15-4) is for Firefox I admit I didn't use this script, but I can tell you that I had no luck directly appending rows to a table in MSIE. (Nothing displayed.) Cured by appending to tbody and then appending tbody to table. Found the cure by Googling. (335) just at the beginning of the function 'make'; See how the function begins: function make(tagname, attributes, children) { // If we were invoked with two arguments the attributes argument is // an array or string, it should really be the children arguments. The comment does not 'really' make sense (English and programming logic wise). I think that it should be rewritten as: function make(tagname, attributes, children) { // If we are invoked with two arguments and the 'attributes' argument is // an array or string, we assume that the second argument is intended // to be the 'children' arguments (ie: the real 'attributes' is missing). // This allows users not to type a null argument in this case. [361] first sample code for Section 16.2.3; The algorithm provided for determining element position fails in some circumstances, at least with Internet Explorer 6. With tables, there is not the expected containment hierarchy of DIV, DIV, TABLE, TBODY, TR, TD, SPAN. Instead, both TR and TD act as though TBODY were their container with respect to position; they provide the same vertical offset. TBODY may also show a vertical offset for a header row when no header is displayed. Either the recipe should be improved, or readers should be warned of its limitations. [380] middle; In the discussion about Computed Styles on page 347 of the fourth edition you discuss getComputedStyle() as a property of document.defaultView. On page 380 of the fifth edition you have dropped this. Unfortunately Safari doesn't have window.getComputedStyle(). Safari does have document.defaultView.getComputedStyle(). This is the way I access the function and the Yahoo! UI library does the same. {382}Last paragraph; In the second sentence of the last paragraph "The HTML DOM Level 2 standard defines a disabled property for both and (858) 4th paragraph from the bottom; The information about the related target properties refers to elements, whereas the last paragraph of page 408 refers to nodes. Both paragraphs are not consistent with each other. As text nodes can be the related target and text nodes are not elements, the paragraph on page 858 should be updated. If it is decided that text nodes should not allowed as a related target, the last paragraph on page 408 should be updated. [876] 4TH EDITION space is missing around HTMLFormElement [896] 4TH EDITION The second argument of the add() method is an index (integer) in IE: try { select.add(theOpt, anOpt); } // standards compliant catch(ex) { select.add(theOpt, indexOfAnOpt); } // IE only [913] innerHeight and innerWidth; innerHeight and innerWidth, under Firefox, are the client area size, including the scrollbars. To have the viewport size, you must use document.documentElement.clientWidth and document.documentElement.clientHeight. Tested on Firefox 2.0. (933) on this page: http://oreilly.com/catalog/9780596101992/errata/9780596101992.807 The following errata is incorrect: Title line for XMLHttpRequest; Internet Explorer 5.0 should be Internet Explorer 7.0 It is actually appropriate to list IE 5 instead of IE 7, because the section below clearly states that IE5 and IE6 support the underlying functionality, simply with a different call. [943] 5 lines from bottom of page; snapshotLength should be readonly long snapshotLength [943] 2 lines from bottom of page; stringValue should be readonly String stringValue