A crash course on JavaScript Objects

JavaScript often gets a bad rap. For those learning to use it for the first time coming from a past in other object-oriented languages like C++ and Java, the most common complaint is that JavaScript “isn’t an object-oriented language” and that it “doesn’t work as it should.” The root of these issues between newcomers and the styles of others languages is often in a misunderstanding how JavaScript works and the way it handles objects internally.

Functions are Objects

In order to create an object as a function in JavaScript, its constructor is called as the function describing it. Anything bound to its ‘this’ function scope is exposed as property members and can be access by referencing the object and name of a property.

JavaScript is not a typed language. For those coming from other, typed languages, this can be confusing. JavaScript is loose with what can be set as the value of properties. They can be Numbers, Strings, Functions, or even other Objects.

By using the ‘new’ keyword, more instantiations of an object can be created from a preexisting constructor function. Instead of assigning a function to a variable, it can be defined and then used multiple times.

All future instantiations of an object have all properties that were described as being bound to it as well as their initial set values.

However, because each instantiation is an object in its own right, its properties can be inherited and then changed too.

In this way, new variables can be copies of preexisting objects and act as parent objects, defining the properties of future, cloned children.

 

Constructor Calling

While it can be convenient to define constructors and other functions for objects as bound to its ‘this’ scope, it is often useful to describe numerous objects and have them inherit from each other. Instead of an object merely being an instance of another object, it can inherit and then add or overwrite its parent’s properties. It can even inherit from multiple parent objects too, mixing their properties together as part of its own.

The easiest way to create this relationship between objects is by using two properties of all Functions: call and apply.

In JavaScript, all objects inherit from an internal Object and come with built-in function as bound to it. Two of these, call and apply, act to change the calling scope of a function. By passing an object to them, the functions being called act as if they were called from that object instead.

(Note: the difference between call and apply is in their arguments. call takes a list and apply uses an array or array-like object.)

 

Prototype Chains

JavaScript is a prototypical language. All objects have properties bound to its ‘this’ scope as well as those defined as part of its prototype. Every object in JavaScript has a prototype property and all of its own properties execute within the same function scope as the object itself. If a property is referenced from an object, its ‘this’ is checked first and, if the property is not found, the properties of an object’s prototype are checked next.

An object’s interface, then, can be defined by binding properties to its prototype to act like functions and properties of an object’s ‘this’ without actually being so.

Every new object that is instantiated from an existing object also inherits all of its previously defined prototype properties too.

 

Implicit (Single) Prototype Inheritance

Just like using call and apply to build objects from the properties of other preexisting objects, it is also possible to bind all of the properties of an object’s prototype to another object. It can inherit not only all of its properties, but its prototype functionality too.

To do this, another function of all objects is used: create.

Object.create uses an object prototype passed to it to build a new object, connecting the enumerable properties of the passed object prototype as the property descriptors of the new object. Through setting an object’s prototype to the Object.create‘d version of another object’s prototype, it binds all of the prototype properties of one object as those of another.

As the final step, the constructor of the newly created object needs to be set. By using the object’s own constructor, it connects back the newly created prototype object as created by its own object.

This method is classical inheritance, allowing one or more children to inherit from (be instances of) both themselves and their parent super-classes.

 

Explicit (Multiple) Prototype Inheritance

JavaScript itself does not provide easy native functionality to mixin, inherit from multiple object prototype chains. However, while all the prototype properties of multiple objects cannot be easily bound, those functions specifically wanted as part of any parent or other objects can be explicitly described and call-ed directly, creating object polymorphism during the function execution.

Because call and apply are part of all functions, they can be used to directly reference parent or other objects. As long as the calling object has the same properties as those referenced within the function being called, the scope can change and return without error.

 

Defining Read-only, Write-only, and Computed Properties

While it can be useful to bind properties to objects using its ‘this’ scope, all properties added or mutated this way are configurable. Without explicitly defining their mutators and options, they can be overwritten or outright deleted during execution without warning.

However, JavaScript does have a way to explicitly mark properties as configurable (changed or deleted), enumerable (listed as a property), or even writable (able to be assigned a value) through another built-in function of Object: createProperty.

By using createProperty (single) or createProperties (multiple), one of more properties can be added to any object and how that property is accessed or changed can be explicitly set.

 

Defining Hybrid-class Prototype Properties

Just as createProperty can be used on any object, it can also be used on any object’s prototype as well. By defining new properties on an object’s prototype, computed values can be returned or function polymorphism performed through the explicitly called functionality of other objects. In effect, any object, as long as it has the same internal properties reference by another function, can adopt as its own that object’s interface or reference its functionality as properties through using call or apply.