JAVASCRIPT

Constructor and Object model

다미르 2019. 9. 4. 16:38

In this post, we will figure out briefly what happens internally when we call a constructor.

It will be needed necessary to understand JS object model and 'this' keyword later.


1. Review

 

Definition of the constructor : 

- It is a function

- It creates an instance and returns it

 

Yes, the constructor is just a function.

If we do not use 'new' keyword, it is just executed and finished without returning the instance.

So whether to call the function using the keyword 'new', shows different results.


2. Keyword 'new'

 

First, here is a sample code of Person object.

function Person(name) {
    this.name = name;
}

Person.prototype.walk = function() {
    console.log(this.name + ' walks');
}

var me = new Person('Nam');

me;
// Person {name: "Nam"}
// name: "Nam"
// __proto__: Object

 

Second, what happens when we call a function(constructor) using the keyword 'new'?

1) clone prototype to create a new object

2) Add property and method

3) Return new object(And it is called 'instance')

var me = (function(name) {
	var instance = {}; // creates new object
    instance.__proto__ = Person.prototype; // clone prototype of Person and delegates it
    instance.name = name; // add property
    return instance; // return instance
})('Nam'); // execute this function immediately

me;
// Person {name: "Nam"}
// name: "Nam"
// __proto__: Object

me.walk(); // Nam walks

 

Third, what if call a function without the keyword 'new'?

var me = Person('Nam');

me; // undefined
window.Nam; // 'Nam'

Since we do not call the constructor, an instance is not returned so the variable 'me' is undefined.

Furthermore, the parameter 'Nam' is bound to the global scope object 'window'.

It is because of the keyword 'this' and we will see more details later.

Just let us focus on what the constructor does.


3. Appendix

 

As I mentioned before, the Function is an Object.

Let's see what happens when we define a function.

 

First. Let's see the below UML :

 

- Red Lines point '__proto__' 

- Blue Lines describe the relationship between constructor and prototype

 

Function 'Person' inherits object 'Function.prototype' using the prototype chain.

So function 'Person' can use all properties and methods of 'Function.prototype'.

 

For example, there is a property 'argument' and it returns the parameter of a function in Array type.

It works in all kinds of functions even though we do not define it.

How is it possible?

Because it is the property of 'Function.prototype', so all functions inherit it using a prototype chain.


Second, look at the above UML closely.

There is one strange thing.

Actually, I painted an object 'orange' and function 'blue'.

 

I told that 'prototype' is working 'object' instance.

But look at the image again.

I painted 'Function.prototype' blue.

Did I make a mistake? 

typeof Object.prototype; // "object"
typeof Array.prototype;  // "object"
typeof Person.prototype; // "object"

// Only Function.prototype is different
typeof Function.prototype; // "Function"

It seems this result is a contradiction, but it is not.

I quote ECMAScript 2015:


The Function prototype object is the intrinsic object 'Function Prototype'.

The Function prototype object is itself a built-in function object.


Consequently, 'typeof Function.prototype' returns "Function" but it is 'built-in' object.

If 'Function.prototype' was a real function, it should have to contain the property 'prototype'.

Function.prototype.prototype; // undefined

But it is not.


Third. 'Object.prototype'

 

This is full version of the object model.

As you can see, all prototypes head to 'Object.prototype'.

'Object.prototype' is the top-level of all objects.

In other words, there is no object behind 'Object.prototype'.

Object.prototype.__proto__; // null