Javascript Basics
This post is about self-learning. I like to note down my understanding of concept that I am learning for better understanding.
Please note that information in this post may not be accurate or not as per standards
Javascript Object - Ways to create javascript object
Factory Pattern
Problem with this approach is that all object created with this will have type of Object so it leads to problem of Object Identification
Constructor Pattern
It solved the Object identification which is great advantage over factory pattern
Contructors defined in this way are defined in global object so window.Person
and window.person
are accessible.
Only difference between functions and contructors is the way they are called, for constructor we use new Person
and functions are called normally
so above contructor can be called like this
var person = new Person("abc", 29); // constructor
Person('abc', 29);
adds to windows object so window.sayName
prints abc
The problem with contructor function is that each object has its own method even though they serve the same purpose, here sayName
is creating for every Person
object. to fix this we can move sayName outside contructor function
but this leads to issue of populating global space with sayName
so we have now window.sayName
function
Prototype Pattern
Each function is created with prototype property, prototype property is an object containing properties and methods that would be available to instance of reference type. As name suggest its actually a prototype of object that will be created when constructor is called. All properties and methods are shared across instances.
When function is created its prototype property is also created and gets a property called constructor that points back to function of which prototype is property of (properties passed through constructor will also be added), so Person.prototype.constructor
points to Person
.
Whenever new instance is created that instance has one internal property (__proto__
or [[Prototype]]
) that points to constructor prototype
not to constructor directly.
Prototype Constructor Instance Relation
Although prototype property are readable but its not possible to overwrite them, for e.g.
hasOwnProperty
hasOwnProperty
can be used to determine if instance has property not prototype so person2.hasOwnProperty("name")
will return false
Object properties can be iterated with for in
, Object.keys
and Object.getOwnPropertyNames
for in
This iterate over all the object property that are enumerable i.e. instance property as well as property present in prototype, so for (var o in person) { console.log(o); }
prints name, age, sayName
ECMAScript 5 sets [[Enumerable]]
to false on the constructor and prototype properties, but this is inconsistent across implementations.
Object.keys
To iterate over instance own enumerable property use Object.keys
so Object.keys(person1)
will give you ["name"]
only and Object.keys(Person.prototype)
will output ["name", "age", "sayName"]
Object.getOwnPropertyNames
Object.getOwnPropertyNames
returns an array for both enumerable and non enumerable object properties, so Object.getOwnPropertyNames
will output ["constructor", "name", "age", "sayName" ]
Both
Object.keys()
andObject.getOwnPropertyNames()
may be suitable replacements for usingfor-in
Alternate Prototype Syntax
In previous prototype pattern notice that we had to type Person.prototype
for all the properties individually, this can be replaced with object literal structure
Please note that with this you are defining a new prototype completely for Person
, end result is same, with one exception the constructor
property no longer points Person
as that now points to new object created. instanceof
will work fine but constructor
will not work
if constructor
is important then use this format
but by adding like this constructor
would become enumerable wherease by normal Prototype constructor
is not enumerable. To fix this you can use Object.defineProperty
Dynamic nature of Prototype
Changes made to prototype are reflected on all instance even if instance was created before protoype
As prototype is assigned when constructor is called so if you define prototype using object literal sytax then it will be only applicable for instance created afterwards
Problems with prototype
First and foremost is that you can pass initialization arguments into constructor, more of a inconvenience rather than problem.
Major issue is that all properties are shared across all the instances. For example
as friends
is property of prototype not instances so change is reflected on all instances
Constructor/Prototype Pattern
The constructor pattern define the instance properties and prototype pattern define methods and other shared properties.
The hybrid constructor/prototype pattern is the most widely used and accepted practice for defining custom reference types in ECMAScript. Generally speaking, this is the default pattern to use for defining reference types.
Inheritance
ECMAScript only supports implementation inheritance i.e. actual methods are inherited not method signatures as methods don’t have signature in ECMAScript
Prototype Chaining
Prototype Chaining Inheritance
Instead of using default prototype of SubType
a new prototype is assigned that points to SuperType
prototype. As SubType.prototype
is instance of SuperType
so it gets properties and methods of SuperType
.
Please note that the getSuperValue
remain on SuperType
but property
is assigned to SubType
as getSuperValue
is prototype method but property
is instance property.
Also note that instance.constructor
points to SuperType, because the constructor property on the SubType.prototype
was overwritten. SubType.prototype = new SuperType();
Working with methods
Sub type can either define new methods or override Super methods but both should be done after protoype has been assigned SubType.prototype = new SuperType();
Another important thing to understand is that the object literal approach to creating prototype methods cannot be used with prototype chaining, because you end up overwriting the chain
Problems with prototype chaining
Prototype references are shared across all instances and When implementing inheritance using prototypes, the prototype actually becomes an instance of another type, meaning that what once were instance properties are now prototype properties.
A second issue with prototype chaining is that you cannot pass arguments into the supertype constructor when the subtype instance is being created. In fact, there is no way to pass arguments into the supertype constructor without affecting all of the object instances
Constructor Stealing
To fix the reference values on prototype issue, constructor stealing was introduced
Problem with this approach is that methods can’t be reused as they are defined inside constructor
Combination Inheritance / pseudoclassical inheritance
combines prototype and constructor stealing inheritance to take advantage of both.
Prototypal Interface
This doesn’t involve strictly type constructor
ECMAScript 5 formalized the concept of prototypal inheritance by adding the Object.create()
Prototypal inheritnace is good if you don’t want to have multiple constructors. Please note that the properties containing reference values will be shared across instances
Parasitic Inheritance
Create a function that does the inheritance and augment the object in some way and returns the object i.e. it performs everything
Problem with Parasitic Interface
Keep in mind that adding functions to objects using parasitic inheritance leads to inefficiencies related to function reuse, similar to the constructor pattern.
More to follow…