Instance Creation Part 3


The previous post we dealt with how “new” works. In this post we will talk about how Object.create works.


var constructorObj = { a:1};
var obj = Object.create(constructorObj)

If we print obj, we will see Object {a: 1}

Firstly, obj is of type Object and not constructorObj.Secondly lets go a little deeper and try


Object.getPrototypeOf(obj)

Object {a: 1}

So basically the constructorObj got attached to the prototype of the new object.That is all it does

Now lets change our constructorObj


constructorObj.a = 2

print obj
Object {a: 2} .So the prototype shares the same object.Any value you change on the object also reflects on the instances.And also obj.constructor points to the native Object

Lets see how it behaves with instances created with new


var constructorFn = function(){this.a=1};
constructorFn.prototype.field1 = "test";
var obj = new constructorFn()
var newObj = Object.create(obj);

Now if we print newObj.We will see

Object {a: 1, field1: “test”}

So the way this happens is newObj[[prototype]]==obj,obj[[prototype]] = constructorFn[[prototype]].

So now if we print Object.getPrototypeOf(Object.getPrototypeOf(newObj)); we will see exactly what we expect Object {field1: “test”} .

Lastly lets see what happens when we pass a function


var obj = Object.create(constructorFn)

If we print obj , we will see Function {}
typeof obj is “object”
obj instanceof Function //true

So what exactly happens ? Well the function gets attached to the prototype .
Object.getPrototypeOf(obj) gives us the original constructorFn. Unlike new there is no change of the this object and hence obj does not get a copy of the properties.

Advertisements

Instance creation part 2


My previous post shows how instance creation works with new operator.So in this post we will try to deduce what really goes on.
We will start with the basic and try and go deep


var constructorFn = function(){this.a=1};
var obj = new constructorFn();
obj instanceof constructorFn // true

Nothing unusual here.When the new keyword is encountered ,the “this” is said to the current object itself and the key value pair is set on the object.

Lets now modify our code a bit


var constructorFn = function(){
this.a =1 ;
}
constructorFn.prototype.key1 ="value1";
constructorFn.prototype.key2 ="value2";

on printing obj we see

constructorFn {a: 1, key1: "value1", key2: "value2"}

So what exactly did happen ? We already understand how a came into the picture.
To understand how the other 2 property came in ,look at the below piece of code

Object.getPrototypeOf(obj);
//displays
Object {key1: "value1", key2: "value2"}

So the algorithm of obj = new fn() goes as follows
1.Execute fn.
2.If “this” is encountered,set its value to the current object
3.If a primitive value is returned then ignore that and set obj to point to the current object
4.If a complex object is returned then obj should ignore the current object and instead be set to the returned value.
5.obj[[prototype]] should now point to fn[[prototype]]

An important thing to understand is that __proto__ and prototype is not same.In the above example


( new Foo ).__proto__ === Foo.prototype ;//true
( new Foo ).prototype === undefined ;//true

__proto__ is the actual object that is used in the lookup chain to resolve methods, etc.Prototype is a property belonging only to functions. Used in case the function happens to be used as a constructor

PS:__proto__ is deprecated and Object.getPrototypeOf should be used.

So the last question remains as to what is the “constructor”.constructor is nothing but the function that constructed the object.

obj.__proto__ === obj.constructor.prototype //returns true
Object.getPrototypeOf(obj) === obj.constructor.prototype //returns true

Why was the last line necessary ? So that we understand that “prototype” is for functions and Object.getPrototypeOf() is for instances.

PPS: Object.getPrototypeOf(obj) === Object.getPrototypeOf(obj.constructor)//returns false .

The reason being getPrototypeOf internally checks the __proto__ property as that is how the chain is traversed and not prototype and hence constructorFn.key1 will be undefined.