Như thường lệ thì các bạn ủng hộ bài viết gốc ở blog của mình tại đây nhé
Chào mừng các bạn trở lại với series tìm hiểu Prototype trong Javascript. Ở phần 1 chúng ta đã được tìm hiểu về:
- Cách để tạo ra một constructor function như thế nào?
- Prototype của function là gì? và cách thêm hàm vào prototype.
- Cách sử dụng Object.create để chia sẽ các hàm dùng chung cho các đối tượng khác nhau.
Bạn nào chưa xem qua phần 1 thì nên đọc trước, trước khi tiếp tục với bài viết hôm nay nhé!
Dưới đây là ví dụ chúng ta đã hoàn thành ở phần 1. Nhìn vào Person
constructor, có thể thấy có 2 dòng quan trọng nhất là tạo ra đối tượng person dùng Object.create
và return nó. Nếu không tạo person với Object.create
thì các đối tượng được tạo ra từ Person
constructor không thể dùng chung các function trong prototype, và nếu thiếu dòng return thì chúng ta cũng không thể lấy được đối tượng person vừa tạo.
1 2 3 4 5 6 7 8 9 10 | <span class="token keyword">function</span> <span class="token function">Person</span> <span class="token punctuation">(</span>name<span class="token punctuation">,</span> mana<span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token keyword">let</span> person <span class="token operator">=</span> Object<span class="token punctuation">.</span><span class="token function">create</span><span class="token punctuation">(</span>Person<span class="token punctuation">.</span>prototype<span class="token punctuation">)</span> person<span class="token punctuation">.</span>name <span class="token operator">=</span> name person<span class="token punctuation">.</span>mana <span class="token operator">=</span> mana <span class="token keyword">return</span> person <span class="token punctuation">}</span> <span class="token keyword">let</span> teo <span class="token operator">=</span> <span class="token function">Person</span><span class="token punctuation">(</span><span class="token string">'Tèo'</span><span class="token punctuation">,</span> <span class="token number">7</span><span class="token punctuation">)</span> |
Hôm nay mình sẽ tiếp tục với ví dụ trên. Chắc có bạn sẽ thắc mắc tại sao ở trên lại cần return person và khi tạo mới đối tượng lại không dùng từ khóa new. Vâng, khi bạn gọi 1 function với từ khóa new, 2 dòng mà mình commented dưới đây được gọi 1 cách ngầm định (“under the hood”) và đối tượng được tạo ra gọi là this
.
1 2 3 4 5 6 7 8 9 10 11 12 | <span class="token keyword">function</span> <span class="token function">Person</span> <span class="token punctuation">(</span>name<span class="token punctuation">,</span> mana<span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token comment">// const this = Object.create(Person.prototype)</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>mana <span class="token operator">=</span> mana <span class="token comment">// return this</span> <span class="token punctuation">}</span> <span class="token keyword">const</span> ti <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">Person</span><span class="token punctuation">(</span><span class="token string">'Tí'</span><span class="token punctuation">,</span> <span class="token number">7</span><span class="token punctuation">)</span> <span class="token keyword">const</span> teo <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">Person</span><span class="token punctuation">(</span><span class="token string">'Tèo'</span><span class="token punctuation">,</span> <span class="token number">10</span><span class="token punctuation">)</span> |
Không có lỗi nào đúng không? Khi chúng ta gọi 1 constructor function với từ khóa new, 1 đối tượng this
được tạo và tự động return. Nhưng nếu bạn quên từ khóa new khi gọi function trên thì sẽ xảy ra lỗi đấy nhé, lúc đó chẳng có this
nào được tạo ra và trả về ngầm định cả. Xem ví dụ dưới đây sẽ rõ:
1 2 3 4 5 6 7 8 9 | <span class="token keyword">function</span> <span class="token function">Person</span> <span class="token punctuation">(</span>name<span class="token punctuation">,</span> mana<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>mana <span class="token operator">=</span> mana <span class="token punctuation">}</span> <span class="token keyword">const</span> ti <span class="token operator">=</span> <span class="token function">Person</span><span class="token punctuation">(</span><span class="token string">'Tí'</span><span class="token punctuation">,</span> <span class="token number">7</span><span class="token punctuation">)</span> console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span>ti<span class="token punctuation">)</span> <span class="token comment">// undefined</span> |
Pattern này được gọi là Pseudoclassical Instantiation
.
ES6 Classes
Nếu bạn là 1 tín đồ của ES6, thì chắc bạn cũng chẳng cần quan tâm đến Prototype là gì đúng ko? ES6 giới thiệu từ khóa Class cho phép chúng ta tạo ra class và đối tượng của nó 1 cách dễ dàng và khỏi đau đầu với những phức cmn tạp của prototype. Bạn có thể xem chi tiết về Class tại đây.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | <span class="token keyword">class</span> <span class="token class-name">Person</span> <span class="token punctuation">{</span> <span class="token function">constructor</span><span class="token punctuation">(</span>name<span class="token punctuation">,</span> mana<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>mana <span class="token operator">=</span> mana <span class="token punctuation">}</span> <span class="token function">eat</span><span class="token punctuation">(</span>amount<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"> đang ăn`</span></span><span class="token punctuation">)</span> <span class="token keyword">this</span><span class="token punctuation">.</span>mana <span class="token operator">+=</span> amount <span class="token punctuation">}</span> <span class="token function">sleep</span><span class="token punctuation">(</span>hours<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"> đi ngủ.`</span></span><span class="token punctuation">)</span> <span class="token keyword">this</span><span class="token punctuation">.</span>mana <span class="token operator">+=</span> hours <span class="token punctuation">}</span> <span class="token function">play</span><span class="token punctuation">(</span>hours<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"> đi chơi với gái.`</span></span><span class="token punctuation">)</span> <span class="token keyword">this</span><span class="token punctuation">.</span>mana <span class="token operator">-=</span> hours <span class="token punctuation">}</span> <span class="token punctuation">}</span> <span class="token keyword">const</span> ti <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">Person</span><span class="token punctuation">(</span><span class="token string">'Tí'</span><span class="token punctuation">,</span> <span class="token number">7</span><span class="token punctuation">)</span> <span class="token keyword">const</span> teo <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">Person</span><span class="token punctuation">(</span><span class="token string">'Tèo'</span><span class="token punctuation">,</span> <span class="token number">10</span><span class="token punctuation">)</span> |
Rõ ràng và dễ hiểu hơn đúng không nào? Vậy thì tại sao chúng ta còn phải tìm hiểu Prototype nữa làm gì, tốn thời gian mà chả được tích sự chi. Vì Javascript là prototype based, nên để hiểu rõ cách class hoạt động, chúng ta phải nắm vững Prototype. Bạn có thể đọc thêm prototype based ở đây
Vậy là chúng ta đã tìm hiểu về Prototype trong Javascript, chúng hoạt động như thế nào và sử dụng chúng ra sao. Sau đây là một vài ví dụ liên quan đến Prototype trong Javascript.
Get một prototype của một Object
Khi bạn muốn get prototype của một object, hãy dùng hàm Object.getPrototypeOf
.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 | <span class="token keyword">function</span> <span class="token function">Person</span> <span class="token punctuation">(</span>name<span class="token punctuation">,</span> mana<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>mana <span class="token operator">=</span> mana <span class="token punctuation">}</span> Person<span class="token punctuation">.</span>prototype<span class="token punctuation">.</span><span class="token function-variable function">eat</span> <span class="token operator">=</span> <span class="token keyword">function</span> <span class="token punctuation">(</span>amount<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"> đang ăn`</span></span><span class="token punctuation">)</span> <span class="token keyword">this</span><span class="token punctuation">.</span>mana <span class="token operator">+=</span> amount <span class="token punctuation">}</span> Person<span class="token punctuation">.</span>prototype<span class="token punctuation">.</span><span class="token function-variable function">sleep</span> <span class="token operator">=</span> <span class="token keyword">function</span> <span class="token punctuation">(</span>hours<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"> đi ngủ.`</span></span><span class="token punctuation">)</span> <span class="token keyword">this</span><span class="token punctuation">.</span>mana <span class="token operator">+=</span> hours <span class="token punctuation">}</span> Person<span class="token punctuation">.</span>prototype<span class="token punctuation">.</span><span class="token function-variable function">play</span> <span class="token operator">=</span> <span class="token keyword">function</span> <span class="token punctuation">(</span>hours<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"> đi chơi với gái.`</span></span><span class="token punctuation">)</span> <span class="token keyword">this</span><span class="token punctuation">.</span>mana <span class="token operator">-=</span> hours <span class="token punctuation">}</span> <span class="token keyword">const</span> ti <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">Person</span><span class="token punctuation">(</span><span class="token string">'Tí'</span><span class="token punctuation">,</span> <span class="token number">7</span><span class="token punctuation">)</span> <span class="token keyword">const</span> prototype <span class="token operator">=</span> Object<span class="token punctuation">.</span><span class="token function">getPrototypeOf</span><span class="token punctuation">(</span>ti<span class="token punctuation">)</span> console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span>prototype<span class="token punctuation">)</span> <span class="token comment">// {constructor: ƒ, eat: ƒ, sleep: ƒ, play: ƒ}</span> prototype <span class="token operator">===</span> Person<span class="token punctuation">.</span>prototype <span class="token comment">// true</span> |
Mặc định, prototype
của object sẽ có một property gọi là constructor
trỏ đến constructor function hoặc class (ES6) đã tạo ra object đó. Đó cũng là lý do vì sao bất kỳ đối tượng nào chúng ta cũng có thể truy cập constructor
của nó thông qua instance.constructor
.
1 2 3 4 5 6 7 8 | <span class="token keyword">function</span> <span class="token function">Person</span> <span class="token punctuation">(</span>name<span class="token punctuation">,</span> mana<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>mana <span class="token operator">=</span> mana <span class="token punctuation">}</span> <span class="token keyword">const</span> ti <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">Person</span><span class="token punctuation">(</span><span class="token string">'Tí'</span><span class="token punctuation">,</span> <span class="token number">7</span><span class="token punctuation">)</span> console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span>ti<span class="token punctuation">.</span>constructor<span class="token punctuation">)</span> <span class="token comment">// constructor function</span> |
Bạn cũng có thể dùng property
__proto__
để get prototype của 1 object, nhưng đây là cách cũ, hiện tại nên dùng hàm Object.getPrototypeOf(instance) nhé.
Kiểm tra 1 property có phải của protype hay không
Trong một số trường hợp cụ thể thì bạn muốn biết một property của object là của chính object đó hay là được lấy từ protype của nó. Bài toán là hãy log tất cả các key và value có trong 1 object, xem ví dụ bên dưới để hiểu hơn, đơn giản mình dùng for in
để lặp qua tất cả các key trong object:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 | <span class="token keyword">function</span> <span class="token function">Person</span> <span class="token punctuation">(</span>name<span class="token punctuation">,</span> mana<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>mana <span class="token operator">=</span> mana <span class="token punctuation">}</span> Person<span class="token punctuation">.</span>prototype<span class="token punctuation">.</span><span class="token function-variable function">eat</span> <span class="token operator">=</span> <span class="token keyword">function</span> <span class="token punctuation">(</span>amount<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"> đang ăn`</span></span><span class="token punctuation">)</span> <span class="token keyword">this</span><span class="token punctuation">.</span>mana <span class="token operator">+=</span> amount <span class="token punctuation">}</span> Person<span class="token punctuation">.</span>prototype<span class="token punctuation">.</span><span class="token function-variable function">sleep</span> <span class="token operator">=</span> <span class="token keyword">function</span> <span class="token punctuation">(</span>hours<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"> đi ngủ.`</span></span><span class="token punctuation">)</span> <span class="token keyword">this</span><span class="token punctuation">.</span>mana <span class="token operator">+=</span> hours <span class="token punctuation">}</span> Person<span class="token punctuation">.</span>prototype<span class="token punctuation">.</span><span class="token function-variable function">play</span> <span class="token operator">=</span> <span class="token keyword">function</span> <span class="token punctuation">(</span>hours<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"> đi chơi với gái.`</span></span><span class="token punctuation">)</span> <span class="token keyword">this</span><span class="token punctuation">.</span>mana <span class="token operator">-=</span> hours <span class="token punctuation">}</span> <span class="token keyword">const</span> ti <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">Person</span><span class="token punctuation">(</span><span class="token string">'Tí'</span><span class="token punctuation">,</span> <span class="token number">7</span><span class="token punctuation">)</span> <span class="token keyword">for</span><span class="token punctuation">(</span><span class="token keyword">let</span> key <span class="token keyword">in</span> ti<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">`Key: </span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span>key<span class="token interpolation-punctuation punctuation">}</span></span><span class="token string">. Value: </span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span>ti<span class="token punctuation">[</span>key<span class="token punctuation">]</span><span class="token interpolation-punctuation punctuation">}</span></span><span class="token string">`</span></span><span class="token punctuation">)</span> <span class="token punctuation">}</span> |
Và mình mong đợi kết quả là:
1 2 3 | Key<span class="token punctuation">:</span> name<span class="token punctuation">.</span> Value<span class="token punctuation">:</span> <span class="token constant">T</span>í Key<span class="token punctuation">:</span> mana<span class="token punctuation">.</span> Value<span class="token punctuation">:</span> <span class="token number">7</span> |
Nhưng đời không như là mơ, run kết quả:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | Key<span class="token punctuation">:</span> name<span class="token punctuation">.</span> Value<span class="token punctuation">:</span> <span class="token constant">T</span>í Key<span class="token punctuation">:</span> mana<span class="token punctuation">.</span> Value<span class="token punctuation">:</span> <span class="token number">7</span> Key<span class="token punctuation">:</span> eat<span class="token punctuation">.</span> Value<span class="token punctuation">:</span> <span class="token keyword">function</span> <span class="token punctuation">(</span>amount<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"> đang ăn`</span></span><span class="token punctuation">)</span> <span class="token keyword">this</span><span class="token punctuation">.</span>mana <span class="token operator">+=</span> amount <span class="token punctuation">}</span> Key<span class="token punctuation">:</span> sleep<span class="token punctuation">.</span> Value<span class="token punctuation">:</span> <span class="token keyword">function</span> <span class="token punctuation">(</span>hours<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"> đi ngủ.`</span></span><span class="token punctuation">)</span> <span class="token keyword">this</span><span class="token punctuation">.</span>mana <span class="token operator">+=</span> hours <span class="token punctuation">}</span> Key<span class="token punctuation">:</span> play<span class="token punctuation">.</span> Value<span class="token punctuation">:</span> <span class="token keyword">function</span> <span class="token punctuation">(</span>hours<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"> đi chơi với gái.`</span></span><span class="token punctuation">)</span> <span class="token keyword">this</span><span class="token punctuation">.</span>mana <span class="token operator">-=</span> hours <span class="token punctuation">}</span> |
Tại sao lại như vậy? Vì loop for in
sẽ lặp qua tất cả các property có trong chính object và kể cả những property trong prototype của nó nữa. Vì vậy, không những chúng ta thấy giá trị của name
và mana
, mà còn có các hàm của prototype eat
, sleep
và play
nữa. Để giải quyết vấn đề này, có thể dùng hàm hasOwnProperty
để kiểm tra xem 1 property có phải là của chính object đó hay không?
1 2 3 4 5 6 7 8 9 10 | <span class="token operator">...</span> <span class="token keyword">const</span> ti <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">Person</span><span class="token punctuation">(</span><span class="token string">'Tí'</span><span class="token punctuation">,</span> <span class="token number">7</span><span class="token punctuation">)</span> <span class="token keyword">for</span><span class="token punctuation">(</span><span class="token keyword">let</span> key <span class="token keyword">in</span> ti<span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token keyword">if</span> <span class="token punctuation">(</span>ti<span class="token punctuation">.</span><span class="token function">hasOwnProperty</span><span class="token punctuation">(</span>key<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">`Key: </span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span>key<span class="token interpolation-punctuation punctuation">}</span></span><span class="token string">. Value: </span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span>ti<span class="token punctuation">[</span>key<span class="token punctuation">]</span><span class="token interpolation-punctuation punctuation">}</span></span><span class="token string">`</span></span><span class="token punctuation">)</span> <span class="token punctuation">}</span> <span class="token punctuation">}</span> |
Kết quả bây giờ đúng như chúng ta mong muốn:
1 2 3 | Key<span class="token punctuation">:</span> name<span class="token punctuation">.</span> Value<span class="token punctuation">:</span> <span class="token constant">T</span>í Key<span class="token punctuation">:</span> mana<span class="token punctuation">.</span> Value<span class="token punctuation">:</span> <span class="token number">7</span> |
Bạn có thể test thêm để kiểm chứng:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 | <span class="token keyword">function</span> <span class="token function">Person</span> <span class="token punctuation">(</span>name<span class="token punctuation">,</span> mana<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>mana <span class="token operator">=</span> mana <span class="token punctuation">}</span> Person<span class="token punctuation">.</span>prototype<span class="token punctuation">.</span><span class="token function-variable function">eat</span> <span class="token operator">=</span> <span class="token keyword">function</span> <span class="token punctuation">(</span>amount<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"> đang ăn`</span></span><span class="token punctuation">)</span> <span class="token keyword">this</span><span class="token punctuation">.</span>mana <span class="token operator">+=</span> amount <span class="token punctuation">}</span> Person<span class="token punctuation">.</span>prototype<span class="token punctuation">.</span><span class="token function-variable function">sleep</span> <span class="token operator">=</span> <span class="token keyword">function</span> <span class="token punctuation">(</span>hours<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"> đi ngủ.`</span></span><span class="token punctuation">)</span> <span class="token keyword">this</span><span class="token punctuation">.</span>mana <span class="token operator">+=</span> hours <span class="token punctuation">}</span> Person<span class="token punctuation">.</span>prototype<span class="token punctuation">.</span><span class="token function-variable function">play</span> <span class="token operator">=</span> <span class="token keyword">function</span> <span class="token punctuation">(</span>hours<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"> đi chơi với gái.`</span></span><span class="token punctuation">)</span> <span class="token keyword">this</span><span class="token punctuation">.</span>mana <span class="token operator">-=</span> hours <span class="token punctuation">}</span> <span class="token keyword">const</span> ti <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">Person</span><span class="token punctuation">(</span><span class="token string">'Tí'</span><span class="token punctuation">,</span> <span class="token number">7</span><span class="token punctuation">)</span> ti<span class="token punctuation">.</span><span class="token function">hasOwnProperty</span><span class="token punctuation">(</span><span class="token string">'name'</span><span class="token punctuation">)</span> <span class="token comment">// true</span> ti<span class="token punctuation">.</span><span class="token function">hasOwnProperty</span><span class="token punctuation">(</span><span class="token string">'mana'</span><span class="token punctuation">)</span> <span class="token comment">// true</span> ti<span class="token punctuation">.</span><span class="token function">hasOwnProperty</span><span class="token punctuation">(</span><span class="token string">'eat'</span><span class="token punctuation">)</span> <span class="token comment">// false</span> ti<span class="token punctuation">.</span><span class="token function">hasOwnProperty</span><span class="token punctuation">(</span><span class="token string">'sleep'</span><span class="token punctuation">)</span> <span class="token comment">// false</span> ti<span class="token punctuation">.</span><span class="token function">hasOwnProperty</span><span class="token punctuation">(</span><span class="token string">'play'</span><span class="token punctuation">)</span> <span class="token comment">// false</span> |
Kiểm tra object là thể hiện của Class nào?
Có lúc bạn muốn biết thèn Tí có phải là con mình hay không? Hay nó là sản phẩm của thèn hàng xóm. Bạn phải nhờ đến bác sĩ để kiểm tra ADN, và ông bác sĩ đưa cho bạn 1 hàm instanceof
và công thức của nó như sau:
1 2 | object <span class="token keyword">instanceof</span> <span class="token class-name">Class</span> |
Bạn là dân coder chuyên nghiệp, và thế là về kiểm tra ngay:
1 2 3 4 5 6 7 8 9 10 11 12 | <span class="token keyword">function</span> <span class="token function">Person</span> <span class="token punctuation">(</span>name<span class="token punctuation">,</span> mana<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>mana <span class="token operator">=</span> mana <span class="token punctuation">}</span> <span class="token keyword">function</span> <span class="token function">User</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span><span class="token punctuation">}</span> <span class="token keyword">const</span> ti <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">Person</span><span class="token punctuation">(</span><span class="token string">'Tí'</span><span class="token punctuation">,</span> <span class="token number">7</span><span class="token punctuation">)</span> ti <span class="token keyword">instanceof</span> <span class="token class-name">Person</span> <span class="token comment">// true</span> ti <span class="token keyword">instanceof</span> <span class="token class-name">User</span> <span class="token comment">// false</span> |
May quá, Tí là con của mình rồi, nhưng bạn muốn chắc chắn hơn, bạn cần biết công thức instanceof
hoạt động như thế nào? Vâng, nó sẽ kiểm tra xem prototype của đối tượng có đúng là prototype của constructor function hay class hay không? Object.getPrototypeOf(ti) === Person.prototype
.
Nghĩ sâu một chút
Bạn có nhận ra lỗi ở đoạn code bên dưới không?
1 2 3 4 5 6 7 | <span class="token keyword">function</span> <span class="token function">Person</span> <span class="token punctuation">(</span>name<span class="token punctuation">,</span> mana<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>mana <span class="token operator">=</span> mana <span class="token punctuation">}</span> <span class="token keyword">const</span> ti <span class="token operator">=</span> <span class="token function">Person</span><span class="token punctuation">(</span><span class="token string">'Tí'</span><span class="token punctuation">,</span> <span class="token number">7</span><span class="token punctuation">)</span> |
Đệt, troll bố à? Tạo object dùng constructor function mà dell dùng từ khóa new. Vâng nếu bạn có câu trả lời như trên thì bạn hoàn toàn hiểu bài rồi đấy. Nhưng không phải ai cũng thông minh như bạn, nhất là mấy thèn IQ thấp và lười biếng như mình.
Chắc bạn nghĩ, ngu thì chịu chứ liên quan gì đến tao . Nhưng lỡ đâu 1 ngày trong team bạn có 1 thèn như thế, khởi tạo đối tượng với constructor function mà bạn đã tạo ra trước đó. Thế là lỗi ở đâu ập đến, crash mẹ con server mà bạn cũng chẳng biết lỗi từ đâu tới nữa, tốn công debug cả ngày, biết đâu bạn lại nhớ đến vấn đề ngày hôm nay.
Như đã đề cập ở trên, nếu chúng ta gọi 1 constructor function với từ khóa new, 1 đối tượng this
sẽ được tạo ngầm định, và instance của this
này chính là constructor function đó:
1 2 3 4 5 6 7 8 9 | <span class="token keyword">function</span> <span class="token function">Person</span> <span class="token punctuation">(</span>name<span class="token punctuation">,</span> mana<span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token keyword">this</span> <span class="token keyword">instanceof</span> <span class="token class-name">Person</span> <span class="token operator">===</span> <span class="token boolean">false</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> console<span class="token punctuation">.</span><span class="token function">warn</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>name<span class="token interpolation-punctuation punctuation">}</span></span><span class="token string"> quên gọi Person với từ khóa new rồi`</span></span><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>mana <span class="token operator">=</span> mana <span class="token punctuation">}</span> |
Thay vì bắn ra lỗi thì bạn có thể gọi luôn function với từ khóa new luôn:
1 2 3 4 5 6 7 8 9 | <span class="token keyword">function</span> <span class="token function">Person</span> <span class="token punctuation">(</span>name<span class="token punctuation">,</span> mana<span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token keyword">this</span> <span class="token keyword">instanceof</span> <span class="token class-name">Person</span> <span class="token operator">===</span> <span class="token boolean">false</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token keyword">return</span> <span class="token keyword">new</span> <span class="token class-name">Person</span><span class="token punctuation">(</span>name<span class="token punctuation">,</span> mana<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>mana <span class="token operator">=</span> mana <span class="token punctuation">}</span> |
Giờ cho dù bạn có quên gọi new đi chăng nữa, thì chương trình vẫn hoạt động đúng.
Arrow Functions
Nếu bạn đã tìm hiểu về Arrow function trong ES6, thì this
được auto binding chứ chúng không chứa this
của chính nó. Vì vậy Arrow functions không được dùng để làm constructor function, nếu bạn cố gắng gọi 1 arrow function với từ khóa new, nó sẽ báo lỗi:
1 2 3 4 | <span class="token keyword">const</span> <span class="token function-variable function">Person</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><span class="token punctuation">}</span> <span class="token keyword">const</span> ti <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">Person</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token comment">// Uncaught TypeError: a is not a constructor</span> |
Chính vì thế, 1 arrow function cũng không có prototype
.
1 2 3 | <span class="token keyword">const</span> <span class="token function-variable function">Person</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><span class="token punctuation">}</span> console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span>Person<span class="token punctuation">.</span>prototype<span class="token punctuation">)</span> <span class="token comment">// undefined</span> |
Vậy là chúng ta đã tìm hiểu qua Prototype trong Javascript và một số ứng dụng thực tiễn. Mong các bạn thấy có ích thì like, share để ủng hộ mình nhé. Hẹn gặp lại các bạn trong các bài viết tiếp theo!