Notes on JavaScript: The Definitive Guide
- When the JavaScript interpreter starts, it creates a new global object and gives it a set of defined initial properties.
- Whenever a property of a string literal is referenced, the string value is converted to an object by calling new String(), and once the reference ends, this temporary object is destroyed.
- The “==” operator treats primitive values and their wrapper objects as equal, while “===” does not.
- Primitive values are immutable; object references are mutable.
- undefined converted to number:
NaN, while null converted to number: 0, empty string converts to 0 and false.
Objects
When the JavaScript interpreter starts, it creates a new global object and gives it a set of defined initial properties.
Whenever a property of a string literal is referenced, the string value is converted to an object by calling new String(), and once the reference ends, this temporary object is destroyed.
The “==” operator treats primitive values and their wrapper objects as equal, while “===” does not.
Primitive values are immutable; object references are mutable.
undefined converted to number:
NaN, while null converted to number: 0, empty string converts to 0 and false.
Object to boolean conversion:
All objects (including arrays and functions) convert to true.
Global scope doesn’t require var, but local variable declarations need var, otherwise a global variable is created by default.
JavaScript has no block-level scope, replaced by function scope, meaning all variables declared within a function are always visible throughout the function body. Variables are available before they are declared, but assignment operations are still executed at their original position, i.e., “hoisting.”
- var truevar = 1; // Declares a non-deletable global variable
- fakevar = 2; // Creates a deletable property of the global object
Use x!=x to determine whether x is NaN.
The in operator:
Returns true if the right-side object has a property with the name of the left operand value.
typeof(null) -> “object”; typeof(undefined) -> “undefined”; commonly used in expressions:
(typeof value == “string”) ? “ ‘ “ + value + “ ‘ “ : value;
Functions are a type of object, but typeof(func) returns “function.”
Deleting a property or array element doesn’t just set an undefined value; the property will no longer exist.
Variables declared with var cannot be deleted, deleting a non-existent property returns true, deleting array elements doesn’t change its length.
The void operator:
Ignores the result of the operand and returns undefined.
for(variable in object) statement; first evaluates the variable value and assigns the property name to it.
break cannot cross function boundaries, while continue can only be used within loop bodies.
&& short-circuit:
When the left operand is truthy, the operator evaluates the right operand and returns it as the result of the entire expression.
hasOwnProperty() is used to check whether a given name is an own property of the object.
Accessor properties:
getter and setter, inheritable, get property(){}, set property(){}.
Data property: value, writability, enumerability, configurability;
Accessor property: get, set, enumerability, configurability.
Once converted to non-extensible, it cannot be converted back. Object.preventExtensions(); adding properties to the prototype of a non-extensible object will still allow it to inherit new properties.
- Object.getOwnPropertyDescriptor() can get the property descriptor of a specific property of an object: ({x:1},”x”).
- Object.defineProperty(o,”x”,{value:1,writable:true,enumerable:false,configurable:true});
- Both functions above do not include inherited properties.
Arrays
Arrays are a special form of JavaScript objects. Array indices are essentially property names that happen to be integers.
Array traversal: 1. Exclude null, undefined, and non-existent elements:
if(!a[i]) continue;
Exclude undefined and non-existent elements:
if(a === undefined) continue;
Exclude non-existent but still process undefined:
if(!(i in a)) continue; or: for(var index in sparseArray){}.
Array methods:
- join():
Converts all elements to strings and concatenates them. Default separator is comma; custom separator can be specified;- reverse():
Reverses the order of elements;- sort():
Sorts in alphabetical order. Numeric sort: a.sort(function(a,b) { return a - b; }); // If the first argument should come first, return a negative number, and vice versa;- concat():
Creates and returns a new array containing the original array and each argument of concat();- slice():
Returns an array containing elements from the first argument position to the second argument position, excluding the second. If one argument, it’s the start position with end at the last element. Negative numbers: -1 represents the last element;- splice():
Unlike slice and concat, it modifies the calling array and returns an array of deleted elements;- push and pop;
- unshift and shift operate at the array head;
JavaScript 5:
- forEach():
Iterates the array, calling the specified function for each element;- map():
Requires return value, returns a new array without modifying the calling array, while forEach() modifies;- filter():
Compress sparse arrays: var dense = sparse.filter(function(){return true;}); // filter skips missing elements in sparse arrays, returned array is always dense;- Remove both undefined and null elements:
a = a.filter(function(x){return x !== undefined && x != null;});- every():
Returns true only when the predicate function returns true for all elements;- some():
Returns true if at least one returns true;- reduce():
var sum = a.reduce(function(x,y) { return x + y }, 0); // The second argument 0 is the initial value;- reduceRight():
Processes from right to left;- indexOf():
Searches the entire array for an element with the given value, returns the index of the first found element, returns -1 if not found;- lastIndexOf():
Reverse search, second argument specifies the starting position.- Determine if it’s an array:
Array.isArray().
Functions
Nested functions do not inherit this from the function that calls them. If a nested function is called as a method, its this points to the object that called it. If called as a function, this is either the global object (non-strict mode) or undefined (strict mode).
When calling new o.m(), the context (this) is not o, but a new empty object created by the constructor invocation.
&&:
If the left operand is falsy, returns the left operand value without evaluating the right; if the left is truthy, evaluates and returns the right operand value;
||:
If the left operand is truthy, returns the left operand value without evaluating the right; if the left is falsy, evaluates and returns the right operand value;
arguments:
A reference to the arguments object, which has a length property but is not a true array.
arguments property:
callee: refers to the currently executing function.
Functions can have their own properties because they are a special type of object.
Functions as namespaces:
( function(){ //codes } () ); // End the function definition and immediately invoke it.
Closures:
JavaScript functions use the scope chain for execution, which is created when the function is defined. No matter when and where the inner nested function f() is executed, variables in f are always local variables.
Each time a JavaScript function is called, a new object is created to hold local variables. This object is added to the scope chain. When the function returns, this variable-binding object is removed from the scope chain.
Nested functions cannot access this unless it’s converted to a variable in the outer function:
var self = this;
Function property:
length: number of formal parameters;
prototype property:
When a function is used as a constructor, newly created objects inherit properties from the prototype object.
Call function f as a method of object o:
f.call(o) or f.apply(o);
bind() method:
var g = f.bind(o); // Call o.f(x) by calling g(x).
Functions created by the Function() constructor do not use lexical scope; function body code is always compiled and executed at the top-level function (global scope).
Partial functions and memoized functions.
Classes and Modules
Calling a constructor:
The constructor’s prototype property is used as the prototype for the new object, inheriting properties from prototype.
Factory function approach vs. constructor approach.
The prototype object is the only identifier of a class. Two objects belong to instances of the same class if and only if they inherit from the same prototype object.
For any function F.prototype.constructor==F; an object’s constructor property refers to this class.
The relationship between constructor and prototype object:

- Any property added to the constructor object (not inside the constructor) is a class field or class method, belonging to the class rather than any specific instance;
- Properties of the prototype object are inherited by all instances of the class. If a prototype property value is a function, it serves as an instance method shared by all instances;
- Defining non-function properties directly on each instance of the class is essentially instance fields.
Even after object creation, changes to the prototype’s properties will affect all instance objects that inherit from this prototype.
- Checking an object’s class: instanceof, isPrototypeOf(). The inheritance doesn’t have to be direct;
- constructor property;
- The above two methods don’t work in multi-window and multi-frame sub-pages, so constructor names can be used instead;
Factory method:


Constructor method:

toJSON() is used for serialization. If an object has a toJSON() method, JSON.stringify() won’t serialize the passed object directly but will call toJSON() instead. JSON.parse() is the reverse process.
forEach:

Private methods:
Simulating private instance fields by closuring variables (or parameters) within a constructor:

Key to creating subclasses:
- B.prototype = inherit(A.prototype); // Subclass derives from parent
- B.prototype.constructor = B; // Override inherited constructor property
Set implementation using composition instead of inheritance:


- Object.preventExtensions(): Makes the object non-extensible, no new properties can be added;
- Object.seal and Object.freeze: Makes all properties read-only and non-configurable.
Object.create(null); // Creates an object without a prototype, enabling direct use of the in operator
Functions as private namespaces:


Creating off-screen images:
new Image(80,20).src = “images/***.gif”;
this:
- Points to the current object of function execution;
- When there’s no explicit current object, points to the global object window.
- In event handler code, the keyword this refers to the document element that triggered the event.
Form element properties:
type, form (read-only reference to the containing Form object), name, value;
Use this.form to reference the Form object, this.form.x to reference a sibling form element named x.Cookie properties:
expires, path, domain, secure.
Function literals and the Function() constructor for creating functions: suitable for one-time use, no naming needed.
The callee property:
Used to reference the currently executing function.
f.call(o,1,2); is equivalent to:
o.m = f; o.m(1,2); delete o.m;
Deleting a property:
delete book.chapter2.
Inside a method body, the value of this becomes the object on which the method was called.
JavaScript objects “inherit” properties from their prototype objects.
Property inheritance only occurs when reading property values, not when writing them.
Instance properties have their own copies, while instance methods are shared by the class.
To create a subclass of class Complex, simply ensure the new class’s prototype object is an instance of Complex, so it inherits all properties of Complex.prototype:
- MoreComplex.prototype = new Complex(0,0);
- MoreComplex.prototype.constructor = MoreComplex;
Object.property is equivalent to Object[“property”] -> associative array.
Only elements actually stored in the array have memory allocated.
Regular expression literal:
var pattern = /S$/; i.e., var pattern = new RegExp(“S$”);
Copying and passing use references, but comparison uses values.
Define methods and constants shared by all class instances by setting the class.prototype property.
- Function() constructor vs. Function literal
- Allows dynamic creation and compilation of JS code at runtime vs. Static
- Each call parses the function body and creates a new function object vs. Opposite
- Does not use lexical scope, acts as top-level function
- null == undefined -> true;
- null === undefined -> false;
JavaScript in Web Browsers
- If scripts in two windows set the Document’s domain property to the same value, the two windows are no longer subject to the same-origin policy and can read each other’s properties.
- When the HTML parser encounters a script tag element, it must by default execute the script first, then resume document parsing and rendering;
- The defer attribute of the script tag:
Makes the browser delay script execution until the document is fully loaded and parsed; executed in order.
- The async attribute:
Makes the browser execute the script as soon as possible without blocking document parsing during script download; may execute out of order.
The Window Object
The Window object’s location property references the Location object:
window.location === document.location //true
The Location object’s toString method returns the value of its href property.
When calling a function in window B from window A, the function executes in the scope where it was defined, not where it was called.
For built-in classes, each window has its own copy of the constructor and a separate copy of the corresponding prototype object.
Scripting Documents
Setting the name or id attribute for certain HTML elements automatically creates corresponding properties on the window and document objects, whose values point to the HTMLElement objects representing those elements.
Selecting elements via CSS selectors:
querySelectorAll(), querySelector(); accepts a string argument containing CSS selectors.
Document, Element, and Text objects are all Node objects. Properties:
parentNode, childNodes, firstChild, lastChild, nextSibling, previousSibling, nodeType, nodeValue, nodeName, textContent.
Element properties:
attributes, innerHTML;
DocumentFragment is a special Node that serves as a temporary container for other nodes.
Scroll position:
window.pageXOffset/pageYOffset;
Querying viewport dimensions:
window.innerWidth/innerHeight;
In HTML5, the input tag’s placeholder attribute specifies the hint message displayed before user input.
The Document type defines methods for creating Element and Text objects:
document.createTextNode(“text node content”);
The Node type defines methods for inserting, deleting, and replacing in the node tree:
- parent.appendChild(child); // Insert at the end of parent element;
- parent.insertBefore(child, parent.childNodes[n]);
- n.parentNode.removeChild(n);
- n.parentNode.replaceChild(document.createTextNode(“[ REDACTED ]”), n);
Scripting CSS
Inline styles:
e.style.position=”relative”;
Computed styles:
window.getComputedStyle(element, null);
Event Handling
Registering event handlers via HTML attributes is an exception; they are converted to top-level functions that can access global variables rather than any local variables.
When a certain type of event is triggered on an object (e.g., onclick click event), if the object has defined a handler for this event, the handler is called. If no handler is defined or the event returns true, the event propagates to the parent object, from inside out, until it is handled (all same-type events of parent objects are activated) or reaches the topmost level of the object hierarchy, i.e., the document object (some browsers use window).
jQuery
- each() can only iterate jQuery objects, while jQuery.each() can iterate array elements or object properties.
- focus and blur events don’t support bubbling, while focusin and focusout do;
- mouseover and mouseout support bubbling, mouseenter and mouseleave don’t;
Notes on JavaScript: The Definitive Guide
http://quanru.github.io/2015/06/15/Notes-on-JavaScript-The-Definitive-Guide

