Functions are 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.
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.
(Note: the difference between call and apply is in their arguments. call takes a list and apply uses an array or array-like object.)
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
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.
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.