ECMAScript 5 allows a trailing comma (after the last property) in an object literal. Alas, not all older browsers support it. A trailing comma is useful, because you can rearrange properties without having to worry which property is last.

Tip

Use the delete operator sparingly. Most modern JavaScript engines optimize the performance of instances created by constructors if their “shape” doesn’t change (roughly: no properties are removed or added). Deleting a property prevents that optimization.

Unusual Property Keys

Numbers can be used as property keys in object literals, but they are interpreted as strings. The dot operator can only access properties whose keys are identifiers. Therefore, you need the bracket operator (shown in the following example) to access properties whose keys are numbers:

Object literals also allow you to use arbitrary strings (that are neither identifiers nor numbers) as property keys, but you must quote them. Again, you need the bracket operator to access the property values:

The array method slice is used to convert arguments to an array, which is necessary for logging it (this operation is explained in Array-Like Objects and Generic Methods). bound is a new function. Here’s the interaction:

A library method

The preceding manual workaround is inspired by a library method published by Mozilla. The following is a slightly edited version of it:

if(!Function.prototype.construct){Function.prototype.construct=function(argArray){if(!Array.isArray(argArray)){thrownewTypeError("Argument must be an array");}varconstr=this;varnullaryFunc=Function.prototype.bind.apply(constr,[null].concat(argArray));returnnewnullaryFunc();};}

An alternative approach

An alternative to the previous approach is to create an uninitialized instance via Object.create() and then call the constructor (as a function) via apply(). That means that you are effectively reimplementing the new operator (some checks are omitted):

Function.prototype.construct=function(argArray){varconstr=this;varinst=Object.create(constr.prototype);varresult=constr.apply(inst,argArray);// (1)// Check: did the constructor return an object// and prevent `this` from being the result?returnresult?result:inst;};

Warning

The preceding code does not work for most built-in constructors, which always produce new instances when called as functions. In other words, the step in line (1) doesn’t set up inst as desired.

Here’s the explanation: we have called the value of counter.inc as a function. Hence, this is the global object and we have performed window.count++. window.count does not exist and is undefined. Applying the ++ operator to it sets it to NaN:

> callIt(counter.inc.bind(counter))
> counter.count // one more than before
2

Warning

Each call to bind() creates a new function. That has consequences when you’re registering and unregistering callbacks (e.g., for event handling). You need to store the value you registered somewhere and use it for unregistering, too.

Inheritance

Whenever you access a property via obj, JavaScript starts the search for it in that object and continues with its prototype, the prototype’s prototype, and so on. That’s why we can access proto.describe via obj.describe. The prototype chain behaves as if it were a single object. That illusion is maintained when you call a method: the value of this is always the object where the search for the method began, not where the method was found. That allows the method to access all of the properties of the prototype chain. For example:

> obj.describe()
'name: obj'

Inside describe(), this is obj, which allows the method to access obj.name.

varjane={name:'Jane',describe:function(){return'Person named '+this.name;}};vartarzan={name:'Tarzan',describe:function(){return'Person named '+this.name;}};

Both objects are persons. Their name property is different, but we could have them share the method describe. We do that by creating a common prototype called PersonProto and putting describe into it (Figure 17-2).

This is a common pattern: the data resides in the first object of a prototype chain, while methods reside in later objects. JavaScript’s flavor of prototypal inheritance is designed to support this pattern: setting a property affects only the first object in a prototype chain, whereas getting a property considers the complete chain (see Setting and Deleting Affects Only Own Properties).

Creating a new object with a given prototype

creates an object whose prototype is proto. Optionally, properties can be added via descriptors (which are explained in Property Descriptors). In the following example, object jane gets the prototype PersonProto and a mutable property name whose value is 'Jane' (as specified via a property descriptor):

varPersonProto={describe:function(){return'Person named '+this.name;}};varjane=Object.create(PersonProto,{name:{value:'Jane',writable:true}});

Here is the interaction:

> jane.describe()
'Person named Jane'

But you frequently just create an empty object and then manually add properties, because descriptors are verbose:

Checking whether one object a prototype of another one

checks whether the receiver of the method is a (direct or indirect) prototype of obj. In other words: are the receiver and obj in the same prototype chain, and does obj come before the receiver? For example:

Finding the object where a property is defined

functiongetDefiningObject(obj,propKey){obj=Object(obj);// make sure it’s an objectwhile(obj&&!{}.hasOwnProperty.call(obj,propKey)){obj=Object.getPrototypeOf(obj);// obj is null if we have reached the end}returnobj;}

__proto__ is pronounced “dunder proto,” an abbreviation of “double underscore proto.” That pronunciation has been borrowed from the Python programming language (as suggested by Ned Batchelder in 2006). Special variables with double underscores are quite frequent in Python.

__proto__ is not part of the ECMAScript 5 standard. Therefore, you must not use it if you want your code to conform to that standard and run reliably across current JavaScript engines.

However, more and more engines are adding support for __proto__ and it will be part of ECMAScript 6.

The following expression checks whether an engine supports __proto__ as a special property:

Option 2 is to implement a function yourself that iterates over all properties (not just enumerable ones). For example:

functiongetAllPropertyNames(obj){varresult=[];while(obj){// Add the own property names of `obj` to `result`result=result.concat(Object.getOwnPropertyNames(obj));obj=Object.getPrototypeOf(obj);}returnresult;}

Object.defineProperties() is explained in Getting and Defining Properties via Descriptors, but it should be fairly obvious how it works: proto has the own properties protoEnumTrue and protoEnumFalse and obj has the own properties objEnumTrue and objEnumFalse (and inherits all of proto’s properties).

Note

Note that objects (such as proto in the preceding example) normally have at least the prototype Object.prototype (where standard methods such as toString() and hasOwnProperty() are defined):

A property descriptor is a data structure for working programmatically with attributes.

Property Attributes

All of a property’s state, both its data and its metadata, is stored in attributes. They are fields that a property has, much like an object has properties. Attribute keys are often written in double brackets. Attributes matter for normal properties and for accessors (getters and setters).

The following attributes are specific to normal properties:

[[Value]] holds the property’s value, its data.

[[Writable]] holds a boolean indicating whether the value of a property can be changed.

[[Configurable]] holds a boolean. If it is false, you cannot delete a property, change any of its attributes (except [[Value]]), or convert it from a data property to an accessor property or vice versa. In other words, [[Configurable]] controls the writability of a property’s metadata. There is one exception to this rule—JavaScript allows you to change an unconfigurable property from writable to read-only, for historic reasons; the property length of arrays has always been writable and unconfigurable. Without this exception, you wouldn’t be able to freeze (see Freezing) arrays.

Defining a property means something different depending on whether a property already exists:

If a property does not exist, create a new property whose attributes are as specified by the descriptor. If an attribute has no corresponding property in the descriptor, then use the default value. The defaults are dictated by what the attribute names mean. They are the opposite of the values that are used when creating a property via assignment (then the property is writable, enumerable, and configurable).
For example:

I usually don’t rely on the defaults and explicitly state all attributes, to be completely clear.

If a property already exists, update the attributes of the property as specified by the descriptor. If an attribute has no corresponding property in the descriptor, then don’t change it. Here is an example (continued from the previous one):

First, create an object whose prototype is proto. Then, if the optional parameter propDescObj has been specified, add properties to it—in the same manner as Object.defineProperties. Finally, return the result. For example, the following code snippet produces the same result as the previous snippet:

Otherwise, if prop is read-only (own or inherited), throw an exception (in strict mode) or do nothing (in sloppy mode). The next section explains this (slightly unexpected) phenomenon in more detail.

Otherwise, if prop is own (and writable), change the value of that property.

Otherwise, there either is no property prop, or it is inherited and writable. In both cases, define an own property prop that is writable, configurable, and enumerable. In the latter case, we have just overridden an inherited property (nondestructively changed it). In the former case, a missing property has been defined automatically. This kind of autodefining is problematic, because typos in assignments can be hard to detect.

The main purpose of enumerability is to tell the for-in loop which properties it should ignore. As we have seen just now when we looked at instances of built-in constructors, everything not created by the user is hidden from for-in.

Additionally, obj has the prototype Object.prototype, which is also mutable.

Layer 3: Constructors—Factories for Instances

A constructor function (short: constructor) helps with producing objects that are similar in some way. It is a normal function, but it is named, set up, and invoked differently. This section explains how constructors work. They correspond to classes in other languages.

varPersonProto={describe:function(){return'Person named '+this.name;}};varjane={[[Prototype]]:PersonProto,name:'Jane'};vartarzan={[[Prototype]]:PersonProto,name:'Tarzan'};

The objects jane and tarzan are both considered “persons” and share the prototype object PersonProto.
Let’s turn that prototype into a constructor Person that creates objects like jane and tarzan. The objects a constructor creates are called its instances. Such instances have the same structure as jane and tarzan, consisting of two parts:

Data is instance-specific and stored in the own properties of the instance objects (jane and tarzan in the preceding example).

Behavior is shared by all instances—they have a common prototype object with methods (PersonProto in the preceding example).

A constructor is a function that is invoked via the new operator. By convention, the names of constructors start with uppercase letters, while the names of normal functions and methods start with lowercase letters. The function itself sets up part 1:

functionPerson(name){this.name=name;}

The object in Person.prototype becomes the prototype of all instances of Person. It contributes part 2:

Person.prototype.describe=function(){return'Person named '+this.name;};

In line (1), you can see that the prototype of an instance created by a constructor Constr is Constr.prototype.

Line (2) reveals another feature of the new operator: you can return an arbitrary object from a constructor and it becomes the result of the new operator. This is useful if you want a constructor to return an instance of a subconstructor (an example is given in Returning arbitrary objects from a constructor).

Usually the context makes it clear which of the two prototypes is meant. Should disambiguation be necessary, then we are stuck with prototype to describe the relationship between objects, because that name has made it into the standard library via getPrototypeOf and isPrototypeOf. We thus need to find a different name for the object referenced by the prototype property. One possibility is constructor prototype, but that is problematic because constructors have prototypes, too:

If myvar is an array from a different realm, then its prototype is the Array.prototype from that realm. Therefore, instanceof will not find the Array.prototype of the current realm in the prototype chain of myvar and will return false. ECMAScript 5 has the function Array.isArray(), which always works:

A constructor usually sets instance properties to initial values. If one such value is a default, then you don’t need to create an instance property. You only need a prototype property with the same key whose value is the default. For example:

/** * Anti-pattern: don’t do this * * @param data an array with names */functionNames(data){if(data){// There is a parameter// => create instance propertythis.data=data;}}Names.prototype.data=[];

The parameter data is optional. If it is missing, the instance does not get a property data, but inherits Names.prototype.data instead.

This approach mostly works: you can create an instance n of Names. Getting n.data reads Names.prototype.data. Setting n.data creates a new own property in n and preserves the shared default value in the prototype. We only have a problem if we change the default value (instead of replacing it with a new value):

In the preceding example, push() changed the array in Names.prototype.data. Since
that array is shared by all instances without an own property data,
n2.data’s initial value has changed, too.

Best practice: don’t share default values

Given what we’ve just discussed, it is better to not share default values and to always create
new ones:

functionNames(data){this.data=data||[];}

Obviously, the problem of modifying a shared default value does not arise if that value is immutable (as all primitives are; see Primitive Values). But for consistency’s sake, it’s best to stick to a single way of setting up properties. I also prefer to maintain the usual separation of concerns (see Layer 3: Constructors—Factories for Instances): the constructor sets up the instance properties, and the prototype contains the methods.

ECMAScript 6 will make this even more of a best practice, because constructor parameters can have default values and you can define prototype methods via classes, but not prototype properties with data.

We can’t add the property data to the instance via assignment, because JavaScript would complain about a missing setter (which it does when it only finds a getter). Therefore, we add it via Object.defineProperty(). Consult Properties: Definition Versus Assignment to review the differences between defining and assigning.
In line (1), we are ensuring that the property constructor is set up properly (see The constructor Property of Instances).

Obviously, that is quite a bit of work, so you have to be sure it is worth it.

Public properties

Remember that given a constructor Constr, there are two kinds of properties that are public, accessible to everyone. First, prototype properties are stored in Constr.prototype and shared by all instances. Prototype properties are usually methods:

The pros and cons of the Crockford privacy pattern

Mediating access to private data via privileged methods introduces an unnecessary indirection. Privileged methods and private functions both destroy the separation of concerns between the constructor (setting up instance data) and the instance prototype (methods).

It’s completely secure

There is no way to access the environment’s data from outside, which makes this solution secure if you need that (e.g., for security-critical code). On the other hand, private data not being accessible to the outside can also be an inconvenience. Sometimes you want to unit-test private functionality. And some temporary quick fixes depend on the ability to access private data. This kind of quick fix cannot be predicted, so no matter how good your design is, the need can arise.

It may be slower

Accessing properties in the prototype chain is highly optimized in current JavaScript engines. Accessing values in the closure may be slower. But these things change constantly, so you’ll have to measure should this really matter for your code.

It consumes more memory

Keeping the environment around and putting privileged methods in instances costs memory. Again, be sure it really matters for your code and measure.

Being able to access private and public data in the same manner is more elegant than using environments for privacy.

It pollutes the namespace of properties

Properties with marked keys can be seen everywhere. The more people use IDEs, the more it will be a nuisance that they are shown alongside public properties, in places where they should be hidden. IDEs could, in theory, adapt by recognizing naming conventions and by hiding private properties where possible.

Private properties can be accessed from “outside”

That can be useful for unit tests and quick fixes. Additionally, subconstructors and helper functions (so-called “friend functions”) can profit from easier access to private data. The environment approach doesn’t offer this kind of flexibility; private data can be accessed only from within the constructor.

It can lead to key clashes

Keys of private properties can clash. This is already an issue for subconstructors, but it is even more problematic if you work with multiple inheritance (as enabled by some libraries). With the environment approach, there are never any clashes.

Figure 17-5 illustrates the idea: the subconstructor Sub should have all of the properties of Super (both prototype properties and instance properties) in addition to its own. Thus, we have a rough idea of what Sub should look like, but don’t know how to get there. There are several things we need to figure out, which I’ll explain next:

Inheriting instance properties.

Inheriting prototype properties.

Ensuring that instanceof works: if sub is an instance of Sub, we also want sub instanceof Super to be true.

Overriding a method to adapt one of Super’s methods in Sub.

Making supercalls: if we have overridden one of Super’s methods, we may need to call the original method from Sub.

When Sub is invoked via new, its implicit parameter this refers to a fresh instance. It first passes that instance on to Super (1), which adds its instance properties. Afterward, Sub sets up its own instance properties (2,3). The trick is not to invoke Super via new, because that would create a fresh superinstance. Instead, we call Super as a function and hand in the current (sub)instance as the value of this.

Object.create() produces a fresh object whose prototype is Super.prototype. Afterward, we add Sub’s methods. As explained in The constructor Property of Instances, we also need to set up the property constructor, because we have replaced the original instance prototype where it had the correct value.

Figure 17-6 shows how Sub and Super are related now. Sub’s structure does resemble what I have sketched in Figure 17-5. The diagram does not show the instance properties, which are set up by the function call mentioned in the diagram.

Ensuring That instanceof Works

“Ensuring that instanceof works” means that every instance of Sub must also be an instance of Super. Figure 17-7 shows what the prototype chain of subInstance, an instance of Sub, looks like: its first prototype is Sub.prototype, and its second prototype is Super.prototype.

This code uses the helper function copyOwnPropertiesFrom(), which is shown and explained in Copying an Object.

Tip

Read “subclasses” as a verb: SubCsubclassesSuperC.
Such a utility function can take some of the pain out of creating a subconstructor: there are fewer things to do manually, and the name of the superconstructor is never mentioned redundantly. The following example demonstrates how it simplifies code.

Antipattern: The Prototype Is an Instance of the Superconstructor

This is not recommended under ECMAScript 5. The prototype will have all of Super’s instance properties, which it has no use for. Therefore, it is better to use the aforementioned pattern (involving Object.create()).

This is the preferred way of converting an object to a number. The default implementation returns this:

> var obj = {};
> obj.valueOf() === obj
true

valueOf is overridden by wrapper constructors to return the wrapped primitive:

> new Number(7).valueOf()
7

The conversion to number and string (whether implicit or explicit) builds on the conversion to primitive (for details, see Algorithm: ToPrimitive()—Converting a Value to a Primitive). That is why you can use the aforementioned two methods to configure those conversions. valueOf() is preferred by the conversion to number:

> 3 * { valueOf: function () { return 5 } }
15

toString() is preferred by the conversion to string:

> String({ toString: function () { return 'ME' } })
'Result: ME'

The conversion to boolean is not configurable; objects are always considered to be true (see Converting to Boolean).

With the preceding pattern, we can make an object the receiver (first argument of call) that is not an instance of Wine, because the receiver isn’t used to find the method Wine.prototype.incAge. In the following example, we apply the method incAge() to the object john:

A function that can be used in this manner is called a generic method; it must be prepared for this not being an instance of “its” constructor. Thus, not all methods are generic; the ECMAScript language specification explicitly states which ones are (see A List of All Generic Methods).

Accessing Object.prototype and Array.prototype via Literals

You can make this shorter by accessing hasOwnProperty via an instance of Object, as created by an empty object literal {}:

{}.hasOwnProperty.call(obj,'propKey')

Similarly, the following two expressions are equivalent:

Array.prototype.join.call(str,'-')[].join.call(str,'-')

The advantage of this pattern is that it is less verbose. But it is also less self-explanatory. Performance should not be an issue (at least long term), as engines can statically determine that the literals should not create objects.

The term array-like can also be seen as a contract between generic array methods and objects. The objects have to fulfill certain requirements; otherwise, the methods won’t work on them. The requirements are:

The elements of an array-like object must be accessible via square brackets and integer indices starting at 0. All methods need read access, and some methods additionally need write access. Note that all objects support this kind of indexing: an index in brackets is converted to a string and used as a key to look up a property value:

> var obj = { '0': 'abc' };
> obj[0]
'abc'

An array-like object must have a length property whose value is the number of its elements. Some methods require length to be mutable (for example, reverse()). Values whose lengths are immutable (for example, strings) cannot be used with those methods.

Pitfall 1: Inheritance Affects Reading Properties

Some operations consider the whole prototype chain and see inherited properties.

Other operations access only the own (noninherited) properties of an object.

You need to choose carefully between these kinds of operations when you read the entries of an object-as-map. To see why, consider the following example:

varproto={protoProp:'a'};varobj=Object.create(proto);obj.ownProp='b';

obj is an object with one own property whose prototype is proto, which also has one own property. proto has the prototype Object.prototype, like all objects that are created by object literals. Thus, obj inherits properties from both proto and Object.prototype.

We want obj to be interpreted as a map with the single entry:

ownProp: 'b'

That is, we want to ignore inherited properties and only consider own properties. Let’s see which read operations interpret obj in this manner and which don’t. Note that for objects-as-maps, we normally want to use arbitrary property keys, stored in variables. That rules out dot notation.

It considers inherited enumerable properties. The reason that no properties of Object.prototype show up here is that all of them are nonenumerable.

In contrast, Object.keys() lists only own properties:

> Object.keys(obj)
[ 'ownProp' ]

This method returns only enumerable own properties; ownProp has been added via assignment and is thus enumerable by default. If you want to list all own properties, you need to use Object.getOwnPropertyNames().

We also need to escape the escaped version of '__proto__' (etc.) to avoid clashes; that is, if we escape the key '__proto__' as '__proto__%', then we also need to escape the key '__proto__%' so that it doesn’t replace a '__proto__' entry. That’s what happens in line (1).

Mark S. Miller mentions the real-world implications of this pitfall in an email:

Think this exercise is academic and doesn’t arise in real systems? As observed at a support thread, until recently, on all non-IE browsers, if you typed “__proto__” at the beginning of a new Google Doc, your Google Doc would hang. This was tracked down to such a buggy use of an object as a string map.

Soon, __proto__ will be disabled. In ECMAScript 6, the special property __proto__ will be disabled if Object.prototype is not in the prototype chain of an object. You can expect JavaScript engines to slowly migrate to this behavior, but it is not yet very common.

The only disadvantage is that you’ll lose the services provided by Object.prototype. For example, a dict object can’t be automatically converted to a string anymore:

But that is not a real disadvantage, because it isn’t safe to directly invoke methods on a dict object anyway.

Recommendation

Use the dict pattern for quick hacks and as a foundation for libraries. In (nonlibrary) production code, a library is preferable, because you can be sure to avoid all pitfalls. The next section lists a few such libraries.