In Javascript, if you want to instantiate an instance object, we will start with constructing a constructor and then using the new
keyword.
That template, maybe a constructor function (old way) or a class (from ECMAScript 2015).
For example:
Method 1 : Use the constructor function:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | <span class="token comment">// Tạo các thuộc tính (property)</span> <span class="token keyword">function</span> <span class="token function">Dog</span> <span class="token punctuation">(</span> name <span class="token punctuation">,</span> color <span class="token punctuation">,</span> type <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 keyword">this</span> <span class="token punctuation">.</span> color <span class="token operator">=</span> color <span class="token punctuation">;</span> <span class="token keyword">this</span> <span class="token punctuation">.</span> type <span class="token operator">=</span> type <span class="token punctuation">}</span> <span class="token comment">// Thêm vào các phương thức (method)</span> Dog <span class="token punctuation">.</span> prototype <span class="token punctuation">.</span> <span class="token function-variable function">bark</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 template-string"><span class="token string">`</span> <span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span> <span class="token keyword">this</span> <span class="token punctuation">.</span> name <span class="token interpolation-punctuation punctuation">}</span></span> <span class="token string"> barks: Go Go Go`</span></span> <span class="token punctuation">)</span> <span class="token punctuation">}</span> <span class="token comment">// Khởi tạo 1 instance object</span> <span class="token keyword">let</span> milu <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 string">'Milu'</span> <span class="token punctuation">,</span> <span class="token string">'Black'</span> <span class="token punctuation">,</span> <span class="token string">'Becgie'</span> <span class="token punctuation">)</span> <span class="token punctuation">;</span> milu <span class="token punctuation">.</span> <span class="token function">bark</span> <span class="token punctuation">(</span> <span class="token punctuation">)</span> <span class="token comment">// Milu barks: Go Go Go</span> |
Method 2 : Use Class
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | <span class="token keyword">class</span> <span class="token class-name">Dog</span> <span class="token punctuation">{</span> <span class="token comment">// Tạo các thuộc tính (property)</span> <span class="token function">constructor</span> <span class="token punctuation">(</span> name <span class="token punctuation">,</span> color <span class="token punctuation">,</span> type <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 keyword">this</span> <span class="token punctuation">.</span> color <span class="token operator">=</span> color <span class="token punctuation">;</span> <span class="token keyword">this</span> <span class="token punctuation">.</span> type <span class="token operator">=</span> type <span class="token punctuation">}</span> <span class="token comment">// Thêm vào các phương thức (method)</span> <span class="token function">bark</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 template-string"><span class="token string">`</span> <span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span> <span class="token keyword">this</span> <span class="token punctuation">.</span> name <span class="token interpolation-punctuation punctuation">}</span></span> <span class="token string"> barks: Go Go Go`</span></span> <span class="token punctuation">)</span> <span class="token punctuation">}</span> <span class="token punctuation">}</span> <span class="token keyword">let</span> milu <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 string">'Milu'</span> <span class="token punctuation">,</span> <span class="token string">'Black'</span> <span class="token punctuation">,</span> <span class="token string">'Becgie'</span> <span class="token punctuation">)</span> <span class="token punctuation">;</span> milu <span class="token punctuation">.</span> <span class="token function">bark</span> <span class="token punctuation">(</span> <span class="token punctuation">)</span> <span class="token comment">// Milu barks: Go Go Go</span> |
But sometimes, I also come across another way:
Method 3 :
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | <span class="token keyword">function</span> <span class="token function">Dog</span> <span class="token punctuation">(</span> name <span class="token punctuation">,</span> color <span class="token punctuation">,</span> type <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 keyword">this</span> <span class="token punctuation">.</span> color <span class="token operator">=</span> color <span class="token punctuation">;</span> <span class="token keyword">this</span> <span class="token punctuation">.</span> type <span class="token operator">=</span> type <span class="token keyword">this</span> <span class="token punctuation">.</span> <span class="token function-variable function">bark</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 template-string"><span class="token string">`</span> <span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span> <span class="token keyword">this</span> <span class="token punctuation">.</span> name <span class="token interpolation-punctuation punctuation">}</span></span> <span class="token string"> barks: Go Go Go`</span></span> <span class="token punctuation">)</span> <span class="token punctuation">}</span> <span class="token punctuation">}</span> <span class="token keyword">let</span> milu <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 string">'Milu'</span> <span class="token punctuation">,</span> <span class="token string">'Black'</span> <span class="token punctuation">,</span> <span class="token string">'Becgie'</span> <span class="token punctuation">)</span> <span class="token punctuation">;</span> milu <span class="token punctuation">.</span> <span class="token function">bark</span> <span class="token punctuation">(</span> <span class="token punctuation">)</span> <span class="token comment">// Milu barks: Go Go Go</span> |
So what are the 3 ways to do this differently and differently? How to do the most convenient and standard?
In response, we understand what happened when using the new
keyword
When using new
to create an instance object, the following happens in turn:
- Create a new, empty Object
- Point the [[Prototype]] (aka
.__proto__
).__proto__
of this empty Object to the.prototype
attribute of the constructor function - Implement the constructor function, with
this
value assigned as the empty Object just created - At the end of the function, return the newly created Object if the constructor function does not return a non-null Object. If it does, it will return the non-null Object
Try verifying by performing the steps above to initialize an instance object
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 | <span class="token comment">// Vẫn là constructor function con chó:</span> <span class="token keyword">function</span> <span class="token function">Dog</span> <span class="token punctuation">(</span> name <span class="token punctuation">,</span> color <span class="token punctuation">,</span> type <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 keyword">this</span> <span class="token punctuation">.</span> color <span class="token operator">=</span> color <span class="token punctuation">;</span> <span class="token keyword">this</span> <span class="token punctuation">.</span> type <span class="token operator">=</span> type <span class="token punctuation">}</span> Dog <span class="token punctuation">.</span> prototype <span class="token punctuation">.</span> <span class="token function-variable function">bark</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 template-string"><span class="token string">`</span> <span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span> <span class="token keyword">this</span> <span class="token punctuation">.</span> name <span class="token interpolation-punctuation punctuation">}</span></span> <span class="token string"> barks: Go Go Go`</span></span> <span class="token punctuation">)</span> <span class="token punctuation">}</span> <span class="token comment">// 1. Tạo một Object mới, trống rỗng</span> <span class="token keyword">let</span> milu <span class="token operator">=</span> <span class="token punctuation">{</span> <span class="token punctuation">}</span> <span class="token comment">// 2. Trỏ thuộc tính [[Prototype]] (aka `.__proto__`) của Object rỗng này tới thuộc tính `.prototype` của constructor function</span> milu <span class="token punctuation">.</span> __proto__ <span class="token operator">=</span> Dog <span class="token punctuation">.</span> prototype <span class="token comment">// 3. Thực hiện constructor function, với giá trị this được gán là chính Object rỗng vừa tạo</span> Dog <span class="token punctuation">.</span> <span class="token function">call</span> <span class="token punctuation">(</span> milu <span class="token punctuation">,</span> <span class="token string">'Milu'</span> <span class="token punctuation">,</span> <span class="token string">'Black'</span> <span class="token punctuation">,</span> <span class="token string">'Becgie'</span> <span class="token punctuation">)</span> <span class="token comment">// 4. Kết quả chúng ta có 1 instance object là milu "được tạo ra thủ công"</span> console <span class="token punctuation">.</span> <span class="token function">log</span> <span class="token punctuation">(</span> milu <span class="token punctuation">)</span> milu <span class="token punctuation">.</span> <span class="token function">bark</span> <span class="token punctuation">(</span> <span class="token punctuation">)</span> |
The above procedure shows that: instance object inherits methods from .prototype of constructor function or class. And the properties will be obtained by implementing the constructor function with the value of this
is the instance object .
This is the point that makes the difference between Method 1 and Method 3 . In Method 3 , methods are added directly to the instance object. Therefore, if you change the .prototype
of the constructor function, the methods directly added will not change.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | <span class="token keyword">function</span> <span class="token function">Dog</span> <span class="token punctuation">(</span> name <span class="token punctuation">,</span> color <span class="token punctuation">,</span> type <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 keyword">this</span> <span class="token punctuation">.</span> color <span class="token operator">=</span> color <span class="token punctuation">;</span> <span class="token keyword">this</span> <span class="token punctuation">.</span> type <span class="token operator">=</span> type <span class="token keyword">this</span> <span class="token punctuation">.</span> <span class="token function-variable function">bark</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 template-string"><span class="token string">`</span> <span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span> <span class="token keyword">this</span> <span class="token punctuation">.</span> name <span class="token interpolation-punctuation punctuation">}</span></span> <span class="token string"> barks: Go Go Go`</span></span> <span class="token punctuation">)</span> <span class="token punctuation">}</span> <span class="token punctuation">}</span> <span class="token keyword">let</span> milu <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 string">'Milu'</span> <span class="token punctuation">,</span> <span class="token string">'Black'</span> <span class="token punctuation">,</span> <span class="token string">'Becgie'</span> <span class="token punctuation">)</span> <span class="token punctuation">;</span> <span class="token comment">// Thay đổi ở .prototype:</span> Dog <span class="token punctuation">.</span> prototype <span class="token punctuation">.</span> <span class="token function-variable function">bark</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 template-string"><span class="token string">`</span> <span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span> <span class="token keyword">this</span> <span class="token punctuation">.</span> name <span class="token interpolation-punctuation punctuation">}</span></span> <span class="token string"> barks: Meo meo meo`</span></span> <span class="token punctuation">)</span> <span class="token punctuation">}</span> milu <span class="token punctuation">.</span> <span class="token function">bark</span> <span class="token punctuation">(</span> <span class="token punctuation">)</span> <span class="token comment">// Vẫn sủa go go</span> |
So is Method 1 different from Method 2 ? The answer is no different than the writing syntax. Instance objects created using Method 1 or Method 2 will inherit methods from the original .prototype
, with properties (and the value of each property) obtained by executing the constructor function.
Easy to see in Method 2 , there are no words related to .prototype. But essentially all the methods declared in a class have been added to the class’s .prototype. Using class
syntax will be more convenient, neat and easier to understand, but it will also be less explicit.
However, the problem has not stopped there. The this
keyword and the appearance of the arrow function
make things a bit more complicated.
Try rewriting method declarations in Method 1 and Method 3 , using the arrow function
as follows:
Method 1
1 2 3 4 5 6 7 8 9 10 11 | <span class="token keyword">function</span> <span class="token function">Dog</span> <span class="token punctuation">(</span> <span class="token string">'name'</span> <span class="token punctuation">,</span> <span class="token string">'color'</span> <span class="token punctuation">,</span> <span class="token string">'type'</span> <span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token operator">...</span> <span class="token punctuation">.</span> <span class="token punctuation">}</span> Dog <span class="token punctuation">.</span> prototype <span class="token punctuation">.</span> <span class="token function-variable function">bark</span> <span class="token operator">=</span> <span class="token punctuation">(</span> <span class="token punctuation">)</span> <span class="token operator">=></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 template-string"><span class="token string">`</span> <span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span> <span class="token keyword">this</span> <span class="token punctuation">.</span> name <span class="token interpolation-punctuation punctuation">}</span></span> <span class="token string"> barks: Go Go Go`</span></span> <span class="token punctuation">)</span> <span class="token punctuation">}</span> <span class="token keyword">let</span> milu <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> milu <span class="token punctuation">.</span> <span class="token function">bark</span> <span class="token punctuation">(</span> <span class="token punctuation">)</span> <span class="token comment">// undefined barks: Go Go Go</span> |
Method 3
1 2 3 4 5 6 7 8 9 10 11 | <span class="token keyword">function</span> <span class="token function">Dog</span> <span class="token punctuation">(</span> <span class="token string">'name'</span> <span class="token punctuation">,</span> <span class="token string">'color'</span> <span class="token punctuation">,</span> <span class="token string">'type'</span> <span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token operator">...</span> <span class="token punctuation">.</span> <span class="token keyword">this</span> <span class="token punctuation">.</span> <span class="token function-variable function">bark</span> <span class="token operator">=</span> <span class="token punctuation">(</span> <span class="token punctuation">)</span> <span class="token operator">=></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 template-string"><span class="token string">`</span> <span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span> <span class="token keyword">this</span> <span class="token punctuation">.</span> name <span class="token interpolation-punctuation punctuation">}</span></span> <span class="token string"> barks: Go Go Go`</span></span> <span class="token punctuation">)</span> <span class="token punctuation">}</span> <span class="token punctuation">}</span> <span class="token keyword">let</span> milu <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> milu <span class="token punctuation">.</span> <span class="token function">bark</span> <span class="token punctuation">(</span> <span class="token punctuation">)</span> <span class="token comment">// Milu barks: Go Go Go</span> |
Why is Method 3 working properly and Method 1 is not?
The reason is because the arrow function
does not define this
by itself, but will go back and find the value of this
at the time the arrow function
is declared. With Method 1 , at the time of declaration, this
is global
or window
, so this.name
is undefined
. Whereas with Method 3 , the main declaration time is Step 3 when the new
keyword works, where this
is assigned the main value as object milu
already. Therefore way 3 will work properly.
As for the class
declaration ( Method 2 ), there is no need to care about this problem, because it does not use the arrow function
.
Conclusion: class
syntax is much more convenient when object-oriented programming in Javascript. If you still decide to use the old syntax, need to understand the principle of inheritance by prototype and how to use this
.
Refer:
https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Classes
https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Operators/new
https://www.taniarascia.com/understanding-classes-in-javascript/