JavaScript is a very flexible language, but at first I didn’t really like it. Perhaps by getting used to OOP and taking that thought to learn about it, I’ve always felt everything here is always messy. Functions and objects are everywhere, they blend together making me sometimes do not know what is happening. But in the end, I like it and if you look at the development process and the purpose it is towards, you can understand somewhat why JavaScript has become so.
As we all know, JavaScript is a scripting language. When manipulating the DOM, it presents itself as a Functional Programing. When the appearance of NodeJs, React, VueJs … then now, only with JavaScript, you can completely use it as an Object Oriented Programing to comfortably draw and also to be more suitable for the work. technology that we are using. This seems to make every developer using JavaScript feel comfortable and not surprised even though just starting with programming or simply switching from a certain language to.
So how can JavaScript help us so effectively? To find out, let’s find out where JavaScript used Function
to create Object
. By understanding this process, perhaps we will always have the answer to the above question.
__proto__
You’ve probably heard a lot about it in the process of using JavaScript. If you already know what it is, you can skip this part, otherwise let’s learn about it together. Let’s take a look at the example below:
1 2 3 4 5 6 7 8 9 10 11 12 13 | <span class="token keyword">const</span> dog <span class="token operator">=</span> <span class="token punctuation">{</span> name <span class="token punctuation">:</span> <span class="token string">'Puppy'</span> <span class="token punctuation">,</span> <span class="token function">run</span> <span class="token punctuation">(</span> <span class="token punctuation">)</span> <span class="token punctuation">{</span> console <span class="token punctuation">.</span> <span class="token function">log</span> <span class="token punctuation">(</span> <span class="token keyword">this</span> <span class="token punctuation">.</span> name <span class="token operator">+</span> <span class="token string">' is running...'</span> <span class="token punctuation">)</span> <span class="token punctuation">}</span> <span class="token punctuation">}</span> <span class="token keyword">const</span> puppy <span class="token operator">=</span> Object <span class="token punctuation">.</span> <span class="token function">create</span> <span class="token punctuation">(</span> dog <span class="token punctuation">)</span> puppy <span class="token punctuation">.</span> <span class="token function">run</span> <span class="token punctuation">(</span> <span class="token punctuation">)</span> <span class="token comment">//=> Puppy is running...</span> console <span class="token punctuation">.</span> <span class="token function">log</span> <span class="token punctuation">(</span> dog <span class="token punctuation">)</span> <span class="token comment">//=> {name: "Puppy", run: ƒ}</span> console <span class="token punctuation">.</span> <span class="token function">log</span> <span class="token punctuation">(</span> puppy <span class="token punctuation">)</span> <span class="token comment">//=> {}</span> |
Everything looks confusing but it is really difficult to understand. It will not be difficult for you to make the opinion that a puppy
seems to have inherited something from a dog
to be able to run
so nicely. But we have also seen that puppy
actually has nothing inside it, so what is the point of this problem?
1 2 3 | dog <span class="token punctuation">.</span> <span class="token function">isPrototypeOf</span> <span class="token punctuation">(</span> puppy <span class="token punctuation">)</span> <span class="token comment">//=> true</span> puppy <span class="token punctuation">.</span> __proto__ <span class="token operator">===</span> dog <span class="token comment">//=> true</span> |
It is understandable that Object.create
has created a new object inherited from an original object, but this is not necessarily inherited, because as in the above example, the puppy
did not actually receive anything. Our puppy
heir has only one privilege: deletgating
what he wants to do for his dog
. And this privilege is hidden by the puppy
in a special property that every object has that __proto__
. We can also conclude that when creating an object from another object using the Object.create
method, the __proto__
of the new object will always point to the original object, unless we use Object.setPrototypeOf
to get it pointing. to another object.
prototype
Through the above example, we all know that __proto__
is a property that every object in JavaScript has. So what about a Function
, of course it is also an object but moreover it also has another special property that has made me very confused that is the prototype
. Let’s see the following example to better understand it:
1 2 3 4 5 6 7 8 9 10 | <span class="token keyword">function</span> <span class="token function">Dog</span> <span class="token punctuation">(</span> <span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token punctuation">}</span> Dog <span class="token punctuation">.</span> prototype <span class="token punctuation">.</span> name <span class="token operator">=</span> <span class="token string">'Puppy'</span> Dog <span class="token punctuation">.</span> prototype <span class="token punctuation">.</span> <span class="token function-variable function">run</span> <span class="token operator">=</span> <span class="token keyword">function</span> <span class="token punctuation">(</span> <span class="token punctuation">)</span> <span class="token punctuation">{</span> console <span class="token punctuation">.</span> <span class="token function">log</span> <span class="token punctuation">(</span> <span class="token keyword">this</span> <span class="token punctuation">.</span> name <span class="token operator">+</span> <span class="token string">' is running...'</span> <span class="token punctuation">)</span> <span class="token punctuation">}</span> console <span class="token punctuation">.</span> <span class="token function">log</span> <span class="token punctuation">(</span> Dog <span class="token punctuation">.</span> prototype <span class="token punctuation">)</span> <span class="token comment">//=> {name: "Puppy", run: ƒ, constructor: ƒ}</span> |
As you can see, I just created a function named Dog
and did nothing with it. However inside this function already has a property named prototype
. As the name implies, the prototype
is a place to build prototypes and then clone to other objects:
1 2 3 4 5 | puppy <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">Dog</span> <span class="token punctuation">(</span> <span class="token punctuation">)</span> puppy <span class="token punctuation">.</span> <span class="token function">run</span> <span class="token punctuation">(</span> <span class="token punctuation">)</span> <span class="token comment">//=> Puppy is running...</span> Dog <span class="token punctuation">.</span> prototype <span class="token punctuation">.</span> <span class="token function">isPrototypeOf</span> <span class="token punctuation">(</span> puppy <span class="token punctuation">)</span> <span class="token comment">//=> true</span> puppy <span class="token punctuation">.</span> __proto__ <span class="token operator">===</span> Dog <span class="token punctuation">.</span> prototype <span class="token comment">//=> true</span> |
By this point, you probably already understand what happened and can confirm that every object created with the keyword new
will have __proto__
pointing to the prototype
of the object that created it (in the case above is the Dog
function). .
Object creation
We have just passed two examples of __proto__
and prototype
. If you notice you can also recognize, through those examples I have used up to 3 ways to create an object:
- Object as literal : Use parentheses
{}
and inside it is a list of properties and methods of the object. - Object.create : Use
Object.create
to create a new object with__proto__
pointing to the original object. - Function constructor : Create an object using the
new
keyword. The new object will have__proto__
pointing to theprototype
of the function that created it.
You might wonder why you don’t mention another type of object creation from class. Eg:
1 2 3 4 5 6 7 8 9 10 11 | <span class="token keyword">class</span> <span class="token class-name">Animal</span> <span class="token punctuation">{</span> <span class="token function">constructor</span> <span class="token punctuation">(</span> name <span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token keyword">this</span> <span class="token punctuation">.</span> name <span class="token operator">=</span> name <span class="token punctuation">}</span> <span class="token function">run</span> <span class="token punctuation">(</span> <span class="token punctuation">)</span> <span class="token punctuation">{</span> console <span class="token punctuation">.</span> <span class="token function">log</span> <span class="token punctuation">(</span> <span class="token string">'Running...'</span> <span class="token punctuation">)</span> <span class="token punctuation">}</span> <span class="token punctuation">}</span> dog <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">Animal</span> <span class="token punctuation">(</span> <span class="token string">'Puppy'</span> <span class="token punctuation">)</span> |
It is true that you can create an object the same way as above, but the truth is that in JavaScript there is no class concept. All you have just seen is a different type of syntax to make JavaScript more friendly for programmers who are familiar with OOP. Deeply hidden behind that shell are still Function
. If you still have questions, you can verify:
1 2 | <span class="token keyword">typeof</span> Animal <span class="token comment">//=> function</span> |
Object as literal
Here’s how to create the simplest and possibly the most common object in JavaScript:
1 2 3 4 5 6 7 8 9 10 | <span class="token keyword">const</span> student <span class="token operator">=</span> <span class="token punctuation">{</span> name <span class="token punctuation">:</span> <span class="token string">'Lam'</span> <span class="token punctuation">,</span> say <span class="token punctuation">:</span> <span class="token keyword">function</span> <span class="token punctuation">(</span> <span class="token punctuation">)</span> <span class="token punctuation">{</span> console <span class="token punctuation">.</span> <span class="token function">log</span> <span class="token punctuation">(</span> <span class="token string">'Hi! I am '</span> <span class="token operator">+</span> <span class="token keyword">this</span> <span class="token punctuation">.</span> name <span class="token punctuation">)</span> <span class="token punctuation">}</span> <span class="token punctuation">}</span> student <span class="token punctuation">.</span> name <span class="token comment">//=> Lam</span> student <span class="token punctuation">.</span> <span class="token function">say</span> <span class="token punctuation">(</span> <span class="token punctuation">)</span> <span class="token comment">//=> Hi! I am Lam</span> |
Perhaps there is no need to say much about how to create an object of this type. It can be understood as a simple key-value
data type, in which the value
is anything you want, but when it is a function
, people will call it a method.
Object.create
When you want to create multiple objects with the same properties or methods, using an object as literal
is not really a good choice. You will have to repeat a lot of the same code and when you want to change something, it is worse than when you create them. At this point you may think of Object.create
.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | <span class="token keyword">const</span> student <span class="token operator">=</span> <span class="token punctuation">{</span> say <span class="token punctuation">:</span> <span class="token keyword">function</span> <span class="token punctuation">(</span> <span class="token punctuation">)</span> <span class="token punctuation">{</span> console <span class="token punctuation">.</span> <span class="token function">log</span> <span class="token punctuation">(</span> <span class="token string">'Hi! I am '</span> <span class="token operator">+</span> <span class="token keyword">this</span> <span class="token punctuation">.</span> name <span class="token punctuation">)</span> <span class="token punctuation">}</span> <span class="token punctuation">}</span> <span class="token keyword">const</span> studentA <span class="token operator">=</span> Object <span class="token punctuation">.</span> <span class="token function">create</span> <span class="token punctuation">(</span> student <span class="token punctuation">)</span> studentA <span class="token punctuation">.</span> name <span class="token operator">=</span> <span class="token string">'Student A'</span> studentA <span class="token punctuation">.</span> <span class="token function">say</span> <span class="token punctuation">(</span> <span class="token punctuation">)</span> <span class="token comment">//=> Hi! I am Student A</span> <span class="token keyword">const</span> studentB <span class="token operator">=</span> Object <span class="token punctuation">.</span> <span class="token function">create</span> <span class="token punctuation">(</span> student <span class="token punctuation">)</span> studentB <span class="token punctuation">.</span> name <span class="token operator">=</span> <span class="token string">'Student AB'</span> studentB <span class="token punctuation">.</span> <span class="token function">say</span> <span class="token punctuation">(</span> <span class="token punctuation">)</span> <span class="token comment">//=> Hi! I am Student B</span> student <span class="token punctuation">.</span> <span class="token function-variable function">say</span> <span class="token operator">=</span> <span class="token keyword">function</span> <span class="token punctuation">(</span> <span class="token punctuation">)</span> <span class="token punctuation">{</span> console <span class="token punctuation">.</span> <span class="token function">log</span> <span class="token punctuation">(</span> <span class="token string">'Hello everyone! I am '</span> <span class="token operator">+</span> <span class="token keyword">this</span> <span class="token punctuation">.</span> name <span class="token punctuation">.</span> <span class="token function">toUpperCase</span> <span class="token punctuation">(</span> <span class="token punctuation">)</span> <span class="token punctuation">)</span> <span class="token punctuation">}</span> studentA <span class="token punctuation">.</span> <span class="token function">say</span> <span class="token punctuation">(</span> <span class="token punctuation">)</span> <span class="token comment">//=> Hello everyone! I am STUDENT A</span> studentB <span class="token punctuation">.</span> <span class="token function">say</span> <span class="token punctuation">(</span> <span class="token punctuation">)</span> <span class="token comment">//=> Hello everyone! I am STUDENT B</span> |
As I explained above, studentA
and studentB
both have __proto__
pointing to student
, so when student
change, they will also be updated with the corresponding changes. It can be seen that Object.create
has done two things:
- Create a new empty object
- Point the
__proto__
of the new object to the original object
To make it easier to imagine, we can also represent them through a simple code:
1 2 3 4 5 6 7 8 9 10 | <span class="token keyword">function</span> <span class="token function">createObject</span> <span class="token punctuation">(</span> object <span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token keyword">let</span> newObject <span class="token operator">=</span> <span class="token punctuation">{</span> <span class="token punctuation">}</span> Object <span class="token punctuation">.</span> <span class="token function">setPrototypeOf</span> <span class="token punctuation">(</span> newObject <span class="token punctuation">,</span> object <span class="token punctuation">)</span> <span class="token keyword">return</span> newObject <span class="token punctuation">}</span> studentA <span class="token operator">=</span> <span class="token function">createObject</span> <span class="token punctuation">(</span> student <span class="token punctuation">)</span> |
The results will certainly be no different.
Function constructor
Returning to the example above about Animal
and change it a bit:
1 2 3 4 5 6 7 8 9 10 11 | <span class="token keyword">function</span> <span class="token function">Animal</span> <span class="token punctuation">(</span> name <span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token keyword">this</span> <span class="token punctuation">.</span> name <span class="token operator">=</span> name <span class="token keyword">this</span> <span class="token punctuation">.</span> <span class="token function-variable function">run</span> <span class="token operator">=</span> <span class="token keyword">function</span> <span class="token punctuation">(</span> <span class="token punctuation">)</span> <span class="token punctuation">{</span> console <span class="token punctuation">.</span> <span class="token function">log</span> <span class="token punctuation">(</span> <span class="token keyword">this</span> <span class="token punctuation">.</span> name <span class="token operator">+</span> <span class="token string">' is running...'</span> <span class="token punctuation">)</span> <span class="token punctuation">}</span> <span class="token punctuation">}</span> dog <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">Animal</span> <span class="token punctuation">(</span> <span class="token string">'Puppy'</span> <span class="token punctuation">)</span> dog <span class="token punctuation">.</span> name <span class="token comment">//=> Puppy</span> dog <span class="token punctuation">.</span> <span class="token function">run</span> <span class="token punctuation">(</span> <span class="token punctuation">)</span> <span class="token comment">//=> Puppy is running...</span> |
I’m not sure what JavaScript actually did after the new
keyword, but the code below can give an overview of the whole process:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | <span class="token keyword">function</span> <span class="token function">createObjectOf</span> <span class="token punctuation">(</span> <span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token keyword">let</span> newObject <span class="token operator">=</span> <span class="token punctuation">{</span> <span class="token punctuation">}</span> <span class="token keyword">let</span> args <span class="token operator">=</span> Array <span class="token punctuation">.</span> <span class="token keyword">from</span> <span class="token punctuation">(</span> arguments <span class="token punctuation">)</span> <span class="token keyword">let</span> constructor <span class="token operator">=</span> args <span class="token punctuation">.</span> <span class="token function">shift</span> <span class="token punctuation">(</span> <span class="token punctuation">)</span> constructor <span class="token punctuation">.</span> <span class="token function">apply</span> <span class="token punctuation">(</span> newObject <span class="token punctuation">,</span> args <span class="token punctuation">)</span> Object <span class="token punctuation">.</span> <span class="token function">setPrototypeOf</span> <span class="token punctuation">(</span> newObject <span class="token punctuation">,</span> constructor <span class="token punctuation">.</span> prototype <span class="token punctuation">)</span> <span class="token keyword">return</span> newObject <span class="token punctuation">}</span> dog <span class="token operator">=</span> <span class="token function">createObjectOf</span> <span class="token punctuation">(</span> Animal <span class="token punctuation">,</span> <span class="token string">'Puppy'</span> <span class="token punctuation">)</span> dog <span class="token punctuation">.</span> name <span class="token comment">//=> Puppy</span> dog <span class="token punctuation">.</span> <span class="token function">run</span> <span class="token punctuation">(</span> <span class="token punctuation">)</span> <span class="token comment">//=> Puppy is running...</span> |
Everything works as expected and now it’s time to come back to see what we did in createObjectOf
:
- The first is to create a new empty object.
- Retrieve the corresponding constructor and arguments from the data to be transferred.
- Use
Function.prototype.apply
to call the function constructor (hereAnimal
) withthis
here asnewObject
. - Point
__proto__
ofnewObject
to theprototype
of the constructor viaObject.setPrototypeOf
. - Finally, return the newly created
newObject
.
That’s all JavaScript has done, maybe in a different way, but the results are no different.
Summary
So we have come together to understand how an object is created in JavaScript and how they inherit each other. Hopefully the article will be useful for those who are still wondering about these issues like I’ve encountered. See you in the following articles.