What gives Vladimir Putin and his low-life Russian thugs the idea that they can commit an act of war against our closest ally? A weak U.S. president, that's what.

What are Trump's business holdings in Russia? How much does he owe Russian firms and banks? If he has nothing to hide, why won't he answer these simple questions?

Republicans wet their collective diaper imagining that Obama was born outside the U.S., or that he was secretly Muslim, but when confronted with a real conflict of interest, they are suddenly silent.

JavaScript Notes

Language notes — ECMAScript 5

JavaScript Notes

Compiled by Jeremy Kelly
www.anthemion.org

These are my personal JavaScript notes, covering implementations deriving from ECMAScript 5. They are here primarily for my convenience, but you are welcome to use them, subject to the terms of the Creative Commons Attribution-ShareAlike 4.0 International License. If you find a mistake, please let me know.

As far as possible, example code follows the Split Notation. Some creative adaptations have been employed.

This page includes a two-column print style. For best results, print in landscape, apply narrow margins, and change the Scale setting in your browser's print options to 60%.

Contents

I am still compiling these notes. Check back later for more.

Syntax

It is possible to end some lines without semicolons, particularly if the next line cannot be parsed as a continuation of the current line. This should be avoided outside of minifiers.

Single-line comments are prefixed with //. Multi-line comments begin with /* and end with */.

Identifiers

Identifiers must begin with letters, underscores, or dollar signs. After the first letter, digits can also be added.

Along with JavaScript keywords, the following reserved words are forbidden for use as identifiers:

  • class
  • const
  • enum
  • export
  • extends
  • import
  • super

When strict mode is enabled, these words are also reserved:

  • arguments
  • eval
  • implements
  • interface
  • let
  • package
  • private
  • protected
  • public
  • static
  • yield

In ECMAScript 3, all Java keywords were reserved.

Primitive types

Booleans

Boolean values are represented with true and false. When evaluated as booleans, falsy values like these are considered to be false:

  • undefined
  • Zero
  • NaN
  • The empty string
  • null

All other values are considered to be truthy.

Numbers

All numbers are represented with double-precision IEEE 754 floats. JavaScript does not provide integer types, but all integer values between -253 and 253 retain full precision in the number type. JavaScript defines global variable Infinity and NaN to represent infinite values and undefined numeric results. As in other languages, NaN is unequal to every value, including itself. A value can be checked for NaN with the global function isNaN. This function also returns true if the value is something other than a number or boolean, though type conversion causes isNaN('') to return false. isFinite returns false if the value is positive or negative infinity, or NaN.

Numbers can be specified with scientific notation, the exponent being marked with E or e:


var gTol = 1E-3;

Hex values are specified by prefixing the number with 0x or 0X. These cannot have fractional components.

Number primitives are wrapped by the Number class. Its methods include:

toString()
toString(base)
Returns a string representation of the number, in decimal, or in the specified base.
toFixed(ct)
Returns a string representation that rounds the number to ct digits after the decimal point.
toPrecision(ct)
Returns a string representation that rounds the number to ct significant digits.

Strings

JavaScript strings are sequences of 16-bit character values. There is no distinct character type. Strings are immutable.

String literals can be surrounded with single or double quotes. Quote characters are escaped with a single backslash. Long strings can be split across lines by ending each line with a backslash inside the string:


var gWarn = "No people ever recognize \
their dictator in advance";

Single backslashes in other positions have no effect, and are excluded from the string.

The usual escape sequences are available:

Sequence Character
\0 Null
\b Backspace
\f Form feed
\n Newline
\f Form feed
\r Carriage return
\t Tab
\v Vertical tab
\\ Backslash
\' Single quote
\" Double quote

An arbitrary character can be specified by combining \x or \u with a number of hex digits:

Sequence Character
\x XX An element from the Latin-1 character set
\u XXXX A Unicode code point

If \0 is followed by a digit, the digit sequence will be interpreted as a octal number, producing an exception if strict mode is enabled, or an unexpected result if it is not. It is safer to specify the null character with \x00.

String primitives are wrapped by the String class. Its properties and methods include:

length
Returns the number of code units in the string. Most characters are represented with a single code unit, but some unusual characters require two.
charAt(index)
Returns the character at the specified index.
substr(start, len)

Returns the substring that begins at start and has length len. If start is negative, it is considered to wrap once around the end of the string.

Note that this method specifies the substring length, unlike the similarly-named substring.

substring(start)
substring(start, next)

Returns the substring that begins at start and stops at the end of the string, or just before next. If either argument is negative, it is considered to equal zero. If either argument is greater than the length, it is considered to equal the length. If start is greater than end, substring acts as if the arguments were reversed.

Note that these methods specify the substring end point, unlike the similarly-named substr. They differ from slice in that arguments do not wrap around the end of the string, and may be reversed. slice is generally preferred.

slice(start)
slice(start, next)
Returns the substring that begins at start and stops at the end of the string, or just before next. If either argument is negative, it is considered to wrap once around the end of the string. The extracted string never wraps forward past the end, so arguments greater than the length are treated as if they were equal to the length.
includes(sub)
includes(sub, start)
Returns true if sub is found within the string, searching from the start of the string, or from index start.
startsWith(sub)
endsWith(sub)
Returns true if the string starts or ends with sub.
indexOf(sub)
indexOf(sub, start)
Returns the index where sub first occurs, searching from the start of the string, or from index start. Returns -1 if it is not found.
lastIndexOf(sub)
lastIndexOf(sub, start)
Returns the index where sub last occurs, searching from the end of the string, or from index start. Returns -1 if it is not found.
search(regex)
Returns the index of the first regular expression match within the string, or -1 if no match is found. The global search flag in the expression is ignored.
match(regex)
Returns an array containing substrings matched by a regular expression. If the global search flag is set in the expression, all matches are returned in the array. If the flag is not set, the first array element contains the first match, if any, and the following elements contain substrings matched by capturing parentheses in the expression, if such are defined. If no match is found, the method returns null.
split(delim)
split(delim, max)
Returns an array containing all substrings delimited by delim, which may be a substring or a regular expression. If max is specified, no more than that number of elements are returned.
replace(orig, new)

Returns a new string that replaces orig with substring new. orig can be a string or a regular expression. If it is a string, only the first match is replaced. If it is a regular expression, and if the expression's global flag is set, all matches are replaced.

It is also possible to specify a replacement function for new. The function accepts the matching substring, the substrings matched by capturing parentheses, if any, the match position, and the original string as arguments, and returns the replacement string.

repeat(ct)
Returns a new string that repeats the original ct times.
trim()
Returns a new string with whitespace removed from its beginning and end.
padStart(len)
padStart(len, pad)
padEnd(len)
padEnd(len, pad)
Returns a new string that extends the original's length to len by adding spaces or iterations of pad to the beginning or end.

As of ECMAScript 5, array syntax can be used to read characters from a string, just like charAt. Because strings are immutable, the characters cannot be modified:


var oCh = gWarn[0];

Special primitive types

undefined is a unique instance of its own dedicated primitive type, as is null.

undefined is assigned to variables that have been declared but not initialized, among other things. If an attempt is made to read a variable that has not been declared, the browser will throw a ReferenceError exception that describes the variable as 'not defined'. This should not be taken to mean that the variable is undefined. Instead, the variable does not exist at all.

null represents the absence of a value, as it does in languages with pointers. null is equal to undefined when compared with the == operator.

Objects

Technically, every instance that is not a primitive type is an object. Even functions are objects in JavaScript, and, like other objects, these can store properties, including other functions. All object variables are references. Objects are never passed by value.

Global values are members of the global object, which is created when the JavaScript interpreter starts. This includes global properties like undefined and NaN, functions like isNaN, constructors like String, and custom globals defined in the script. Within a browser, the global object also serves as the Window object.

An object can be serialized by passing it to JSON.stringify, which returns a string containing a JSON representation. The object can be deserialized with JSON.parse. JSON represents data with a subset of the JavaScript object literal syntax.

Properties

Property names need not qualify as identifiers. In fact, any quoted string can serve as a name, even the empty string:


var oLook = {
  "Site E": 108,
  "Site F": 90,
  "": 0
};

In this sense, objects are more like maps than traditional class or structure instances. If a particular name is not a valid identifier, it must be dereferenced with the array syntax:


var oCd = oCdsFromName["Site E"];

This syntax also allows the name to be specified with a variable:


var oKey = "Num";
var oNum = oRack[oKey];

When using the array syntax, nested objects:


var gPrefs = {
  Def: { Name: "New", LenMax: 10 }
};

are accessed by concatenating dereference operators, just as a nested array would be:


gPrefs["Def"]["Name"] = "OBSOLETE";

Properties can be added to an object by assigning to them. There is no need to declare the property:


oRack.Num = 10;

Because arrays and functions are objects, properties can be added to them in the same way. Adding a property to an array does not change its length unless the name is a valid index that is outside the current index range.

with

Passing an object to with causes identifiers in the statement or block that follows it to be interpreted as properties of that object, if possible:


with (oData) {
  St = "ACT";
  Alloc(++IdxAct);
  ...
}

Using with is generally discouraged, and it is disallowed in strict mode.

Accessor properties

As of ECMAScript 5, JavaScript can define getters and setters that are read and written like ordinary class variables, but are backed by functions. Properties defined this way are known as accessor properties.

Accessors are declared in object literals by prefixing the backing functions with get and set. Although overloading is normally not supported in JavaScript, both functions are named after the property they define:


var oRef = {
  Num: 0,
  get Cd() { return "F" + this.Num; },
  set Cd(a) { this.Num = a.substring(1); }
}

The setter accepts a single parameter that represents the rvalue in a property assignment:


oRef.Cd = "F10";

As expected, omitting the getter produces a read-only property, and omitting the setter produces one that is write-only. Accessors are inherited like other methods. If a setter is called from a child object, any property it sets will be added to the child so that it hides the parent value, as usual.

Accessors can be added to existing objects with Object.defineProperty or Object.defineProperties.

Property attributes

In ECMAScript 5, properties have attributes that determine whether they are enumerable, whether they can be reconfigured or deleted, and whether their values can be changed. Attributes are also used to create accessor properties.

The attributes for a single property can be set by passing the object, the name of the property, and a property descriptor to Object.defineProperty. If the property already exists, and if it is configurable, it will be modified. If it does not exist, it will be created:


Object.defineProperty(oRef, "Cd", {
  get: function () { return "F" + this.Num; },
  set: function (a) { this.Num = a.substring(1); },
  enumerable: true,
  configurable: true
});

Multiple properties can be configured by passing the object to Object.defineProperties, along with a second object associating one or more property names with descriptors:


Object.defineProperties(oRef, {
  Cd: {
    get: function () { return "F" + this.Num; },
    set: function (a) { this.Num = a.substring(1); },
    enumerable: true,
    configurable: true
  },
  Rank: {
    get: function () { return (this.Num <= 3 ? "A" : "B") }
  }
});

A descriptor can be retrieved by passing the object and property name to Object.getOwnPropertyDescriptor. The object must be the one that originally defined the property, not a descendent.

A descriptor is an object with up to four properties, each defining a specific attribute. A data descriptor configures an ordinary, non-accessor property:

Attribute Value
value The property's starting value.
writable Set to true if the value can be changed. When false, the only way to change the value is to reconfigure it with Object.defineProperty or Object.defineProperties. Even setters in the same object cannot change read-only values. Normally, writing to an inherited property creates a new property in the child, leaving the parent unchanged, but even this is disallowed for read-only inherited properties.
enumerable Set to true if the property can be enumerated by for/in loops or functions like Object.keys.
configurable Set to true if the property can be configured by another call to Object.defineProperty or Object.defineProperties, or if it can be deleted. Attempting to reconfigure a non-configurable property produces a TypeError exception.

An accessor descriptor configures an accessor property:

Attribute Value
get The accessor's getter implementation.
set The accessor's setter implementation.
enumerable Controls enumerability, as above.
configurable Controls configurability, as above.

When creating new properties, value, get, and set default to undefined, while writable, enumerable, and configurable default to false. If neither value, writable, get, nor set are specified, the object is assumed to be a data descriptor.

When reconfiguring properties, unspecified attributes are left unchanged.

Testing properties

The existence of a property can be tested in several ways. The property can be strictly compared with undefined:


var oCkCd = (aParams.Cd !== undefined);

but this fails to distinguish undeclared properties from those that have been explicitly set to undefined.

The in operator accepts a string operand on the left and an object on the right. It returns true if the string is the name of a property, inherited or otherwise, whether its value is undefined or not:


var oCkCd = "Cd" in aParams;

It also accepts a number and an array. It returns true if the number is a valid index for the array:


var oCk10 = 10 in aVals;

The Object.hasOwnProperty method returns true if its string argument names an own property, rather than one that is inherited. The Object.propertyIsEnumerable method also returns true for own properties, as long as they are also enumerable.

Enumerating properties

The for/in loop iterates the names of enumerable properties within some object, including those of inheritied properties. In ECMAScript 5, the Object.keys method also identifies enumerable properties, but it returns an array of names, and it excludes inherited properties. The Object.getOwnPropertyNames method returns a similar array, but non-enumerable properties are included.

Deleting properties

The delete operator removes a property from an object. The property can be referenced with the dot notation:


delete aParams.Cd;

or the array notation:


delete aParams["Cd"];

The operator can also target an array element:


delete oEls[10];

Deleting an element does not change the array size as reported by length, it merely sets the element to undefined. However, if the array is iterated with a for/in loop, the deleted element will be skipped.

If the targeted property or element does not exist, delete fails silently. Inherited properties cannot be deleted through the child; they must instead be deleted through the parent to which they were added.

Creating objects

Object literals

Objects can be initialized with object literals, which contain property/value pairs within curly braces. Each property is separated from its value by a colon, and multiple pairs are delimited with commas:


var oRt = {
  Region: gRegionDef,
  Zone: 0
};

Omitting the properties produces an empty object:


var oRack = {};

Constructors

As in other languages, a constructor is a function that initializes new objects, though in JavaScript, the function is not a member of the type. As will be seen, constructors are often used to store class-static variables and methods. They are invoked like functions, but they are preceded by the new keyword:


var oRg = new tRg(2, 8);

This causes an empty object to be created and passed to the constructor, where it is referenced with this:


function tRg(aMin, aMax) {
  this.Min = aMin;
  this.Max = aMax;
}

Unlike other functions, if the constructor has no parameters, its parentheses can be omitted during the call.

Constructors are not meant to return values. If an object is returned, the first constructed object will be replaced with the returned value. If a non-object value is returned, it will be ignored.

Note that the new object's constructor property is not necessarily set to reference the function just invoked. The constructor has a prototype property, that object has a constructor property, and that value is assigned to the new object's constructor. By default, this will reference the actual constructor, but it can be changed in the prototype.

Object.create

In ECMAScript 5, objects can also be instantiated with the Object.create method. This method accepts an argument that specifies the object's prototype:


var oData = Object.create(tData.prototype);

Note that the new object's constructor property is set to the constructor of the prototype, even though that function was not called.

An optional second argument can be used to define one or more properties. Like Object.defineProperties, this parameter accepts an object that maps property names to property descriptors:


oRef = Object.create(Object.prototype, {
  Cd: {
    get: function () { return "F" + this.Num; },
    set: function (a) { this.Num = a.substring(1); },
    enumerable: true,
    configurable: true
  },
  Rank: {
    get: function () { return (this.Num <= 3 ? "A" : "B") }
  }
});

Inheritance

JavaScript relies on prototypal inheritance, which has little in common with traditional OOP inheritance. In JavaScript, inheritance describes a relationship between objects rather than types. Inheritance for a particular object is determined by the private prototype property, which references the parent object, or null if there is no parent. A class in JavaScript is simply the set of objects that share a given prototype.

When a property is accessed, it is first sought within the referencing object. If that object has not declared the property, it is sought within the object's prototype. The prototype is another object. If it does not declare the property, its prototype is checked, and so on, until a null prototype is encountered. In this way, every object inherits all the properties of its ancestors, including methods, throughout the prototype chain. Properties that have not been inherited are called own properties.

A child does not inherit copies of the ancestor properties; it links in the most literal sense to the parent and its current state. If a property changes in the parent, the same change will be observed in the child. However, assigning to that property in the child creates a new property that hides the original, unless the inherited property is read-only. If the property is an inherited accessor with a setter, that setter will be called, though any property it assigns will again produce a property in the child that hides the parent value.

An object's prototype is assigned when the object is created. Every function has a prototype property that references a default prototype object. When the function is used as a constructor, the prototype is automatically assigned to the new object:


function tOpts() {
  ...
};
var oOpts = new tOpts();

Because every function has this property, every function can theoretically be used as a constructor, though seldom to useful effect. The default prototype for each function contains a non-enumerable constructor property that references the original function. Overwriting the function's prototype breaks this link:


tOpts.prototype = {
  Ct: function () {
    ...
  },
  ...
};

The constructor property can be restored manually, or the problem can be avoided by adding custom properties to the default, rather than overwriting it entirely:


tOpts.prototype.Ct = function () {
  ...
};

Every object has a constructor property that references the constructor that was used to create it. In ordinary usage, this matches the constructor property in the object's prototype.

The Object.create method accepts an object parameter, and assigns that parameter as the prototype of the returned object:


var oOpts = Object.create(tOpts.prototype);

When this is used, the object's constructor is set to match the constructor property in the prototype. An object can also be created with an object literal, which causes Object.prototype to be assigned as the object's prototype, and Object as its constructor.

If the prototype's constructor property is maintained, all objects in the class will also share a common constructor, at least by default. This allows class-static variables and methods to be defined in and accessed through the constructor. These could not be added to the prototype, as that would cause the values to be inherited and shared.

To summarize the standard usage:

  • Non-static variables are added to the object, and this is typically done inside the constructor;
  • Non-static methods are added to the constructor prototype, which becomes the object prototype;
  • Static variables and methods are added to the constructor.

When one class subclasses another, the prototype of the subclass prototype is made to reference the superclass prototype. The subclass prototype constructor is then set to reference the subclass constructor, rather than the superclass constructor. The subclass constructor typically uses call to invoke the superclass constructor on the subclass this.

Testing inheritance

An object's class is determined by its prototype. The instanceof operator accepts an instance on the left and a constructor on the right. It returns true if the instance is an object, and if it inherits from the object referenced by the constructor's prototype property, whether directly or indirectly. Adding properties to the object does not change this result. By extension, the operator typically returns true if the right operand is Object, since all objects inherit from Object.prototype, at least by default. Similarly, arrays can be identified by setting the right operand to Array. The isPrototypeOf function also indicates whether one object is the ancestor of another, though it is invoked on the prototype, and receives the child as an argument.

The object's prototype can be retrieved by passing the object to the Object.getPrototypeOf method, and it can be set by calling Object.setPrototypeOf, though this is discouraged for performance reasons. Most browsers also support the non-standard accessor property __proto__, which provides read and write access to the prototype.

Object attributes

An extensible object is one to which new properties can be added. An object's extensibility can be checked by passing it to Object.isExtensible. It is made non-extensible by passing it to Object.preventExtensions, and once this is done, the object cannot be made extensible again.

A sealed object is non-extensible, and its properties are non-configurable as well. To determine whether an object is sealed, pass it to Object.isSealed. To seal the object, make it non-extensible, then make its properties non-configurable by setting their attributes, or pass the object to Object.seal. A sealed object cannot be unsealed.

A frozen object is sealed, and all its properties are read-only. To determine whether an object is frozen, pass it to Object.isFrozen. To freeze the object, seal it, and make its properties read-only by setting their attributes, or pass the object to Object.freeze. A frozen object canot be unfrozen.

Arrays

JavaScript arrays inherit from Array.prototype. They are typically created with array literals, which are comma-delimited value sequences inside square braces:


var oInsPend = [ "A11", "B04", "CXX" ];

When commas are listed without intervening values, succeeding values are indexed and the array length set as though values had been provided. The last trailing comma before the closing brace is ignored, however:


var oInsMark = [ , "NUL", , ];
gAssert(oInsMark[1] === "NUL");
gAssert(oInsMark.length === 3);

Though the array length includes them, the missing values do not define actual elements. In particular, those indices will not be iterated by for/in loops. They can be dereferenced to produce undefined, but that is true for any invalid index.

Arrays can also be created with the Array constructor. Calling Array without an argument produces an empty array. Passing a single numeric argument creates an array with the specified length, but again, without defining actual elements. Passing multiple arguments, or a single non-numeric argument assigns those values as elements, much like an array literal:


var oInsPend = new Array("A11", "B04", "CXX");

JavaScript arrays are untyped, so different types can be mixed in the same instance. Arrays are indexed with 32-bit unsigned integers, allowing over four billion elements to be stored. The element count is given by the length property. Because arrays are objects, and because the array syntax can also be used to reference ordinary object properties, negative numbers, non-integer numbers, and other invalid indices can be used to read or write values, and the resulting properties are enumerable, but they do not change the array length. Dereferencing an index that is out of range produces undefined, like any attempt to read an undeclared property from an object.

The length property can be modified to truncate or extend the array. Assigning to a valid index that is greater than or equal to the current length also extends the array, and in both cases, the length is increased without adding enumerable elements.

Multidimensional arrays must be implemented as arrays of arrays.

The Array class includes methods such as:

join()
join(delim)
Returns a string containing the string representation of every element, delimited by commas or by delim.
slice(start)
slice(start, next)
Returns a new array containing the elements that begin at start, and stop at the array's end, or just before next. If either argument is negative, it is considered to wrap once around the end of the array. The extracted array never wraps forward past the end, so arguments greater than the length are treated as if they were equal to the length.
concat()
Returns a new array containing the original elements, plus any arguments passed to the function. Unlike splice, if one or more arguments are themselves arrays, their elements are added, rather than the arrays as a whole.
reverse()
Reverses the element order in place, then returns the modified array.
sort()
sort(compare)
Sorts the elements in place, then returns the modified array. By default, elements are sorted by their string representations, so numbers are not sorted in increasing order. To customize the sort, pass a compare function that accepts two values, and returns a positive number if the second should be sorted after the first, zero if they are equal, and a negative number if the first should be sorted after the second.
splice(start)
splice(start, len)
splice(start, len, ...)
Removes elements from the array, or inserts them, or does both, then returns any removed elements in a new array. The operation begins at position start. If no other arguments are provided, this element and those that follow it are removed and returned. If a len is specified, that number of elements are removed. If more arguments are provided, those values are inserted at start. Unlike concat, array arguments are inserted as arrays.
push(el, ...)
Adds one or more elements to the end of the array, then returns its new length.
pop()
Removes one element from the end of the array and returns it.
unshift(el, ...)
Adds one or more elements to the beginning of the array, then returns its new length.
shift()
Removes one element from the beginning of the array and returns it.

In ECMAScript 5, additional methods are provided. These include:

indexOf(val)
indexOf(val, start)
Returns the index of the first element that is equal to val, or negative one if no match is found. If start is specified, the search begins at that position. If start is negative, it is considered to wrap once around the end of the string. If start is greater than the last index, the search fails.
lastIndexOf(val)
lastIndexOf(val, start)
Returns the index of the last element that is equal to val, or negative one if no match is found. If start is specified, the search begins at that position. If start is negative, it is considered to wrap once around the end of the string. If start is greater than the last index, the search begins at the last element.

The following methods accept a call function that itself accepts up to three values: an element, its array index, and the array as a whole. These array methods also accept an optional this parameter. When this is provided, it is referenced wherever this is used within call:

forEach(call)
forEach(call, this)
Iterates the array and passes each element to function call.
map(call)
map(call, this)
Iterates the array, passes each element to function call, and returns a new array containing the values returned by call.
filter(call)
filter(call, this)
Iterates the array, passes each element to function call, and returns a new array containing the elements for which call returned true.
some(call)
some(call, this)
Iterates the array and returns true if call returns true for any element.
every(call)
every(call, this)
Iterates the array and returns true if call returns true for every element.

The following methods accept a callAcc function that itself accepts up to four values: an accumulator that stores an ongoing calculation, an element, its array index, and the array as a whole:

reduce(callAcc)
reduce(callAcc, init)
Iterates the array, passes each element to function callAcc, and returns the last value produced by that function. If init is provided, iteration begins at the first element, and init is used as the first accumulator value. If it is not provided, iteration begins at the second element, with the first being used as the accumulator.
reduceRight(callAcc)
reduceRight(callAcc, init)
Iterates the array in reverse, passes each element to function callAcc, and returns the last value produced by that function. If init is provided, iteration begins at the last element, and init is used as the first accumulator value. If it is not provided, iteration begins at the penultimate element, with the last being used as the accumulator.

Array-like objects

Some objects, like the arguments object defined within functions, are known as array-like objects. These are not true arrays, but they can sometimes be used as if they were. Every such object:

  • Provides a length property;
  • Associates a number of property values with integer indices.

Though they are not Array instances, many Array.prototype methods can be applied to these objects with Function.call or Function.apply.

Regular expressions

Regular expressions are stored in instances of the RegExp class. Instances can be created with the RegExp constructor:


var oRegCd = new RegExp("A[1-3]");

or with regular expression literals, which surround the expression with forward slashes:


var oRegCd = /A[1-3]/;

Most characters are expected to match exactly within the target text. Others have special meanings within the expression:


\ / | . * + ^ $ ? : = ! [ ] { } ( )

To match one of these characters, it is usually necessary to escape it with a single backslash.

Tabs and other non-printing characters are specified with the same escape sequences used in ordinary strings, with the exception of the backspace character, which is matched by [\b]. Additionally, a given control character ctrl-X can be specified as \c X.

The trailing slash may be followed by one or more letters that set flags:


var oRegCmds = /F\d\d/ig;

The letters can also be passed as a second parameter to the RegExp constructor. Flags are used to configure the search:

Flag Effect
i Produces a case-insensitive search.
m Enables multi-line mode, which causes ^ and $ to match the beginning or end of lines, as well as the text as a whole.
g Produces a global search, allowing some functions to process matches beyond the first.

Character classes

Expressions can also use character classes, each of which matches one of a number of characters. Enclosing characters with square braces produces a character set, which matches any one of the contained characters:


var oRegNumLot = /[123]/;

Prefixing the characters with a caret negates the set, so that it matches one character that is not within the braces:


var oRegCdLot = /[^123]/;

A range of characters is specified by joining the lower and upper limits with a hyphen:


var oRegDigOct = /[0-7]/;

Neither . nor * are treated as special characters within a set, so they need not be escaped.

Other classes include:

Class Match
. Any character that is not a newline.
\s Any ASCII or Unicode whitespace character.
\S Any character that is not matched by \s.
\d Any ASCII number character.
\D Any character that is not matched by \d.
\w Any ASCII letter, number, or underscore character. Note that accented or non-roman characters are not included.
\W Any character that is not matched by \w.

Entire sequences can be matched against a set of alternatives by delimiting sub-expressions with the pipe character:


var oRegRt = /(MAIN\d|AUX\d\d|OFF) /;

Sub-expressions are checked from left to right, and the first to produce a match is used, even if another would match more completely.

Quantifiers

Characters and sub-expressions can be followed by quantifiers that allow them to repeat in the target text:

Quantifier Effect
? Match once, or not at all.
* Match zero or more times.
+ Match one or more times.
{ct} Match exactly ct times.
{min} Match at least min times.
{min, max} Match at least min times, but no more than max.

Because they allow characters to be matched zero times, quantifiers like ? and * can produce expressions that match all strings, since every string contains zero or more instances of a given character.

By default, quantifiers implement greedy matches that consume as much of the target text as possible before the remainder is matched with the rest of the expression. Although ? is itself a quantifier, it can also be added to the end of a quantifier to specify a lazy match that consumes as little of the text as is needed to produce a match between the remainder, and the rest of the expression.

Capturing parentheses

Surrounding characters with parentheses produces a sub-expression that can be modified as a whole by a quantifier or another function:


var oReg = / (XO)+ /;

These capturing parentheses also store the target substring matched by the sub-expression. The substring can be recalled in another part of the expression by prefixing the sub-expression number with a backslash:


var oRegChQuot = /(["']).\1/;

The recalled substring is matched only if the target text contains an exact repetition of the substring that matched the referenced sub-expression. The characters inside non-capturing parentheses are prefixed by ?:.


var oReg = / (?:XO)+ /;

These do not store the matching substring.

Anchors

Normally, expressions are matched wherever possible within the target text. Matches can be constrained to certain positions in the text with anchors. These are not matched to characters, but to positions between characters:

Anchor Position
^ The beginning of the text, or the beginning of any line, if the multi-line flag is set.
$ The end of the text, or the end of any line, if the multi-line flag is set.
\b

The beginning or end of a word, which is any point between a \w character and a \W, or between a \w and the beginning or end of the text. Line breaks are already non-word characters, so there is no need to set the multi-line flag.

Note that [\b] is used to match the backspace character.

\B Any point that is not the beginning or end of a word, as defined by \b.

Enclosing characters with parentheses and prefixing with ?= or ?! creates a lookahead, which also constrains the match relative to its surroundings:

Lookahead Effect
patt(?=post) Matches patt if it is followed immediately by post, without consuming or matching post.
patt(?!post) Matches patt if it is not followed immediately by post.

RegExp methods

The RegExp class offers methods that search for matches within a string:

exec(text)
Returns an array containing a substring matched by the regular expression, plus substrings matched by capturing parentheses in the expression, if such are defined. The array also defines an index property that gives the position of the match within text, and an input property that returns text itself. If the global search flag is set in the expression, the method also sets the lastIndex property within the expression instance to the position just after the match. This position becomes the starting point for the next search, if exec is called again. If no match is found, exec returns null.
test(text)
Returns true if a substring is matched by the regular expression. If the global search flag is set, the method also sets the lastIndex property within the expression instance to the position just after the match. This position becomes the starting point for the next search, if test is called again.

A number of String methods also use regular expressions, including search, match, split, and replace.

Operators

Logical operators

JavaScript offers the usual logical operators:

Operator Effect
! Logical complement
&& Logical AND
|| Logical OR

Neither && nor || necessarily returns a boolean value. If the left && operand is falsy, the operator immediately returns that value. If the operand is truthy, it returns the right operand, whether that happens to be truthy or falsy. Conversely, if the first || operand is truthy, it returns that value, otherwise it returns the second operand.

Because undefined is falsy, the || operator can be used to select the first defined value from a set of identifiers:


function gExec(aCt) {
  var oCt = aCt || this.CtDef || 0;
  ...

Because the ! operator always returns a boolean, !! can be used to convert truthy or falsy values to boolean equivalents.

The ternary conditional operator ?: works as in other languages, though it is also capable of returning two different types.

Bitwise operators

The bitwise operators work as they do in other languages, but the operands are treated as 32-bit integers. Integer bits outside this range are discarded, as are fractional components:

Operator Effect
~ Bitwise complement
& Bitwise AND
| Bitwise OR
^ Bitwise XOR
<< Left shift
>> Right shift with sign
>>> Right shift with zeros

Right shift with sign conserves the high-order bit, so it effectively divides by powers of two, even if the left operand is negative. Right shift with zeros inserts zeros instead. The right operand of all shift operations must be between zero and 31. Negative right operands cause the operator to return zero, while operands greater than 31 are treated as operand % 32.

Arithmetic operators

The arithmetic operators function mostly as expected. However:

  • All numbers are floats, so instead of raising an exception, dividing a non-zero number by zero produces Infinity or -Infinity. Dividing zero by zero produces NaN;
  • The modulus operator % also works with non-integer values, and when it produces a remainder, its sign matches that of the first operand;
  • The unary plus operator + can be used to convert non-numeric types to numbers.

Equality operators

The loose equality operators == and != check for general equivalence, so various type conversions are allowed. By contrast, the strict equality operators === and !== check for equivalence and verify that the operands have the same type. When applied to arrays, functions, and other objects, both varieties check for identity, so distinct but otherwise identical instances are not strictly equal. There is no operator that tells whether distinct objects or arrays contain the same properties and values.

Other operators

void

The void operator accepts a single operand, which it evaluates. It then discards the result and returns undefined.

Sequence operator

As in other languages, the sequence operator evaluates both its operands and returns the value on the right:


var oYOrig = (++oX, ++oY);

Because this operator has the lowest possible precedence, a sequence expression must be parenthesized if its result is to be assigned.

typeof

The typeof operator returns a string that gives the general type of its operand, whether "undefined", "boolean", "number", "object", or "function". null variables are considered to have the "object" type.

Type conversion

JavaScript is permissive about type conversions, and most values are automatically converted to other types when required:

  • undefined produces NaN when converted to a number, while null produces zero. Both produce false when converted to a boolean;
  • true produces one and false produces zero when converted to a number;
  • Numbers are automatically converted to strings. Zero and NaN values produce false when converted to booleans, while other numbers produce true;
  • The empty string is converted to zero or false, as required. Strings that contain valid decimal numbers are converted to those numbers automatically, while other strings produce NaN. The empty string produces false when converted to a boolean, while non-empty strings produce true;
  • Empty arrays produce the empty string when converted to strings, while a non-empty array produces a comma-delimited list of its elements. Empty arrays produce zero when converted to a number. Arrays containing a single number or numeric string produce that number when converted to a number, while multi-element arrays and those containing non-numeric elements produce NaN. All arrays produce true when converted to booleans;
  • Objects produce their toString result when converted to strings, or their toString or valueOf results when converted to numbers. Objects always produce true when converted to booleans.

These conversions are used when comparing values with the == operator, so undefined is equal to null, "1" is equal to one, and "0" is equal to false. When a string is added to any other type with the + operator, the non-string type is converted to a string.

Explicit conversions are performed by passing values to the Boolean, Number, String, or Object constructors. For values other than undefined and null, a string can also be produced by invoking the value's toString method.

Strings can also be converted to numbers with the global parseFloat function, which trims the string of leading whitespace and trailing non-numeric characters, and returns NaN if the string is not a valid number. The global parseInt function works similarly, but it only converts integers, and it accepts hexadecimal input if the string begins with 0x or 0X. parseInt also allows the number base to be specified.

Variables

Variables are declared with the var keyword. Multiple variables can be declared and optionally initialized in the same line by separating them with commas:


var oX = 0.0, oY;

Uninitialized variables have the undefined value. Redeclaring a variable has no effect. If the new declaration also initializes the variable, it is simply assigned with the new value.

In strict mode, a variable must be declared before it is assigned, or an error will result. When strict mode is disabled, assigning an undeclared variable automatically declares it within the global object, even if the assignment occurs in a function. Reading from an undeclared variable always produces an error.

A variable declared within a function is accessible throughout the function, even from points before its declaration. This effect is called hoisting. If the variable is read before the declaration, its value will be undefined.

Variables have no type, so a value of one type can be overwritten with another type at any time.

Control structures

switch

switch statements are allowed to branch on conditional values of any type. Strict equality is used when comparing conditional values against case values, and case values can be expressions that are evaluated at run time. case blocks that do not break or return fall through to the next block.

for and for/in

Unlike many languages, JavaScript allows loop variables defined within the initialization statement of a for loop to be accessed outside the loop:


for (var o = 0; o < oCt; ++o) {
  ...
}
var oIdxMatch = o;

Because they are hoisted, such variables can even be used before they are declared.

The for/in loop iterates over an array, and its loop variable is also accessible from outside:


for (var o in oEls)
  if (Ck(oEls[o])) break;
var oIdxMatch = o;

Note that the loop variable iterates array indices rather than array elements. for/in can also iterate the enumerable properties of an object, including those that were inherited. In this case too, it iterates property names rather than values:


for (var oProp in oData)
  gOut(oProp + ": " + oData[oProp]);

Labels

Normally, the break statement causes the innermost loop or switch to end, while continue causes the innermost loop to iterate. An outer loop can be targeted by prefixing the loop statement with a label, consisting of a label name followed by a colon:


zMain: while (true) {
  zBls: for (var oIdxBl in oBls) {
    for (var oIdxMsg in oMsgs)
      switch (oMsgs[oIdxMsg]) {
        case "HOLD": continue zBls;
        case "DONE": break zMain;
        ...

If break is followed by a label name, the specified loop will end. If continue is followed by a name, that loop will iterate.

Functions

A function declaration consists of the function keyword, the function name, and a parameter list. Any type can be returned by any function, so there is no type in the signature. Parameters are also untyped:


function gReset(aPos, aCkSync) {
  ...

Defining the function within an expression produces a function expression. Though it is permissible to provide a function name, these definitions are typically anonymous:


var gReset = function (aPos, aCkSync) {
  ...

Function instances can also be created with the Function constructor:


var gPow2 = new Function("aExp", "return 1 << aExp;");

The last argument is a string that gives the implemention for the new function. The preceding arguments, if any, are strings containing the names of the new function's parameters. The new function is always executed as if it were defined in the global scope, so closures cannot be created this way.

JavaScript does not allow functions to be overloaded. If a second function is declared with the same name, that function replaces the first. Default parameters are not explicitly supported, but all parameters are optional, so default values can be set within the function.

Function declarations can be nested within other functions, but, in strict mode, they can be placed only at the top level of the containing function, or within a block. Function expressions can appear anywhere. Like variables, nested function declarations are hoisted, allowing them to be called before they are declared. Although hoisted variables are undefined before they are initialized, hoisted declarations can be used at any point.

A method is a function that has been assigned to a property in some object. Functions assigned to array elements are also treated as methods. In JavaScript, functions are themselves objects that can contain their own properties, including additional methods.

Functions are sometimes used as namespaces. A global function is defined, variables and functions are declared and used within it, and the containing function is called immediately after. This avoids the name conflicts that can occur when objects are added to the global scope. The pattern is typically known as the Immediately-Invoked Function Expression or IIFE:


(function () {
  ...
}());

Without the outer parentheses, the interpreter would read this as a function declaration, which is required to specify a name. Only expressions are allowed within parentheses.

Invoking functions

JavaScript allows functions to be called without specifying all or any of their arguments. When this is done, the parameters are undefined within the function. Conversely, when a result is read from a function that has not returned a value, undefined is produced.

If a function is called with extra arguments, they are ignored. Within the function, the array-like arguments object can be used to access these and other arguments. arguments was originally presented as a property of the Function prototype, but that has been deprecated; it is now a local variable within the function. arguments can be used to implement variadic functions. arguments has a length property that gives the actual argument count. The function also has a length property, and this gives the parameter count.

this

Within most methods, this refers to the object or array through which the method was invoked. Within a constructor, this refers to the new instance, even if the constructor is itself a method.

In strict mode, within functions that are neither methods nor constructors, this is undefined. It is also undefined within nested functions, even those nested within methods. Before ECMAScript 5, or when strict mode is disabled, this references the global object.

Every function inherits call and apply methods that invoke the function itself. If an argument is passed to either method, that value is referenced by this when the function is executed. When strict mode is enabled, this can be made to reference a primitive type, null, or undefined. Before ECMAScript 5, or when strict mode is disabled, primitive types are replaced with wrapper objects, while null and undefined cause this to reference the global object.

When call is invoked with more than one argument, the additional arguments are forwarded to the function. The second apply argument is expected to be an array. If that argument is specified, its elements are passed as arguments to the function.

Closures

A closure binds one or more functions to a persistent copy of the context in which they were defined. Returning a nested function produces a closure that can access variables or call functions in the containing scope, even after the program exits the containing function. The containing function can also return an object that declares multiple functions, allowing the closure data to be targeted by different operations. This is another way that function scope can be used to limit access to functions and data. All functions within the closure share the same function scope data, but each invocation of the containing function creates a new context with a distinct copy of that data.

this is a keyword, not a variable, so its meaning changes when a function is invoked in different contexts. The this value can be copied to a variable, which can then included in a closure, or the function can be wrapped in a bound function that defines its own this.

Bound functions are created with the bind method, which is inherited by all functions. bind returns a new function that wraps the original. Within the new function, this is set to the value of the first bind argument. If additional arguments are passed to bind, those are forwarded to the original function every time the bound function is invoked. If arguments are passed to the bound function, those are also forwarded to the original, following the permanently bound arguments, if any.

Exceptions

Any type can be thrown, but the JavaScript interpreter only throws Error and its subclasses. Error describes the exception with its name and message properties. The Error function can be used as a constructor:


throw new Error("gExec: Invalid name");

but it also creates and returns an instance without new:


throw Error("gExec: Invalid name");

A try block is followed by a catch block, a finally block, or both. A given catch collects all exceptions in the try block, regardless of type. The catch must define an exception variable, even if it is not needed:


try {
  ...
}
catch (oExcept) {
  ...
}
finally {
  ...
}

Miscellanea

Strict mode

The "strict mode" directive is an ordinary string that enables strict mode. This mode offers language and security improvements, including:

  • Instead of creating a new global variable, writing to an undeclared variable produces a ReferenceError exception;
  • Instead of referencing the global object, this is undefined within non-class functions;
  • The with statement is disallowed;
  • Attempting to change a read-only property, or attempting to add or delete a property from a read-only object produces an exception;
  • Instead of being interpreted as octal values, integer literals that begin with zero produce SyntaxError exceptions;
  • Neither arguments nor eval are allowed to be assigned to another object or function;
  • Variables and functions declared within code passed to eval are not added to the containing scope.

The directive must be the first non-comment line in the script; if placed anywhere else, it is silently ignored. It is ignored altogether in versions before ECMAScript 5.

eval

The global eval function accepts a single string and executes it as JavaScript code. Generally, the code behaves as if it were run from the calling scope. However:

  • If either the calling code or the eval code uses strict mode, then the eval code will be executed within a temporary scope. If strict mode is not enabled, variables declared within eval code will persist after the function returns;
  • If eval is assigned to another variable, and if the function is called from that variable, its code will be executed within the global scope.

The code can always access and modify existing variables in the calling scope.

eval returns the value of its last statement, or undefined if that statement has no value. It also throws unhandled exceptions that were thrown within its code. If the code cannot be parsed, eval throws a SyntaxError exception.

debugger

The debugger statement pauses script execution and shows the debugger, like a breakpoint.

Sources

JavaScript Pocket Reference, 3rd Edition
David Flanagan
2012, O'Reilly Media, Inc.

JavaScript: The Definitive Guide, 6rd Edition
David Flanagan
2011, O'Reilly Media, Inc.

JavaScript & JQuery
Jon Duckett
2014, John Wiley & Sons, Inc.

MDN: String
Retrieved January 2018

MDN: Object.defineProperty()
Retrieved February 2018

MDN: Function.prototype.bind()
Retrieved February 2018

MDN: Regular Expressions
Retrieved February 2018

Stack Overflow: Explain the encapsulated anonymous function syntax
Retrieved February 2018