We’ll look at the 4 instantiation styles: functional, functional shared, prototypal, and pseudoclassical.
In the functional instantiation style, we create a constructor function with one object inside and assign properties and methods to it. The constructor function returns the object. Everything is inside the constructor function.
Each time we create a new instance in functional style, we are creating a new object with all the properties and methods. If there is a lot of data or code in the properties and methods, each instance has the potential to take up a lot of memory.
The advantage to functional is that it is easy to read and understand quickly.
2. Functional Shared
In the functional shared instantiation style, we create a constructor function with one object inside and assign properties to it. The constructor function returns the object.
What about methods? We create a separate object outside the function and assign properties to it that are methods.
In order for instances (or the objects we create via the constructor function) to have access to those methods, we use an extend function. The extend function copies properties from one object to another. (Remember that if the properties are complex types such as functions, the property does not make a new copy in memory, but it references the original). We can either write our own extend function or use a library’s such as Underscore.
Functional shared takes less memory than plain functional instantiation. With extend in functional shared instantiation, the instance copies properties but only references the methods (each instance does not have all the code of the methods).
In prototypal instantiation style, we create a constructor function with one object inside and assign properties to it. The constructor function returns the object.
What about methods? We can even use the function’s built-in prototype property and simply assign properties to it that are methods.
In order for the object to have access to those functions, we use Object.create(). To use Object.create(), we pass in the object we want failed look ups to go to. This creates a prototype chain. This way if our instance does not have the method, the interpreter would look follow the prototype chain and fall back on the separate object (or prototype)’s methods.
Prototypal style saves more memory than functional shared because each instance does not copy all of the prototype’s properties nor reference the prototype’s methods. Instead when the interpreter runs into a failed look up, it will go up the prototype chain. It will look at the prototype’s methods. There is no copying with prototype chains.
In pseudoclassical style, we create a constructor function.
In this function, there are some behind the scenes lines of code that the interpreter runs that we do not have to explicitly write. At the very beginning of the class constructor function, it runs something like this = Object.create(ClassNameHere.prototype). The interpreter creates an object and passes in the respective prototype property.
Inside the function, we assign properties. At the very end of the constructor function, we do not need to write a return statement because the interpreter runs another behind the scenes line of code that returns the object for us.
Outside of the function, we can assign the class’ prototype methods.
This is all possible when we instantiate with the keyword ‘new.’ It is the ‘new’ keyword that has the interpreter run the behind the scenes lines of code. If we instantiate without the keyword ‘new’ and wrote our constructor in pseudoclassical style, we are going to get bugs.