Prototype Pattern trong Javascript
Trong một ngôn ngữ linh hoạt như Javascript, bạn có thể áp dụng rất nhiều những pattern khác nhau. Tùy vào từng trừng hợp mà chúng ta có thể áp dụng. Object oriented programing hay OOP thì các bạn đã nghe và sử dụng chúng rất là nhiều rồi. Nhưng mà trong Javascript thì ta còn có một hướng programing khác, gọi là prototype. Giờ hãy cũng thử xem prototype có gì thú vị và những ích lợi khi sử dụng prototype nhé.
Prototype
Pattern này thì được focus vào việc giúp tạo object từ một blueprint có trước, đồng thời những object sau sẽ được thừa kế những method, thuộc tính khác nhau. Tính chất này gọi là prototype inheritance.
Khi tạo một object trong ES6, bạn đã quen với việc khai báo với class. Trong ES5 thì ta còn có cách khác là function constructor. Giả sử khi viết game ta muốn xây dựng một lớp Warrior như sau:
1 2 3 4 5 6 7 8 | <span class="token keyword">function</span> <span class="token function">Warrior</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 keyword">const</span> harryPotter <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">Warrior</span><span class="token punctuation">(</span><span class="token string">'Harry Potter'</span><span class="token punctuation">)</span> <span class="token keyword">const</span> ngan <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">Warrior</span><span class="token punctuation">(</span><span class="token string">'Ngan'</span><span class="token punctuation">)</span> <span class="token keyword">const</span> snake <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">Warrior</span><span class="token punctuation">(</span><span class="token string">'Snake'</span><span class="token punctuation">)</span> |
Với cách trên, 3 chiến binh đã được tạo ra. Chúng cùng chia sẻ với nhau một contructor là Warrior
1 2 3 4 5 | harryPotter<span class="token punctuation">.</span>constructor <span class="token operator">===</span> ngan<span class="token punctuation">.</span>constructor <span class="token comment">// true</span> snake<span class="token punctuation">.</span>constructor <span class="token operator">===</span> ngan<span class="token punctuation">.</span>constructor <span class="token comment">// true</span> console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span>harryPotter<span class="token punctuation">.</span>constructor<span class="token punctuation">.</span>name<span class="token punctuation">)</span> <span class="token comment">// Warrior</span> |
Giả sử, giờ lớp chiến binh ta muốn có những skill khác nhau như bash, slash thì sao
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | <span class="token keyword">function</span> <span class="token function">Warrior</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>hp <span class="token operator">=</span> <span class="token number">100</span> <span class="token keyword">this</span><span class="token punctuation">.</span><span class="token function-variable function">bash</span> <span class="token operator">=</span> <span class="token keyword">function</span><span class="token punctuation">(</span>target<span class="token punctuation">)</span> <span class="token punctuation">{</span> target<span class="token punctuation">.</span>hp <span class="token operator">-=</span> <span class="token number">10</span> <span class="token punctuation">}</span> <span class="token keyword">this</span><span class="token punctuation">.</span><span class="token function-variable function">slash</span> <span class="token operator">=</span> <span class="token keyword">function</span><span class="token punctuation">(</span>target<span class="token punctuation">)</span> <span class="token punctuation">{</span> target<span class="token punctuation">.</span>hp <span class="token operator">/=</span> <span class="token number">2</span> <span class="token punctuation">}</span> <span class="token punctuation">}</span> harryPotter<span class="token punctuation">.</span><span class="token function">bash</span><span class="token punctuation">(</span>ngan<span class="token punctuation">)</span> console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span>ngan<span class="token punctuation">.</span>hp<span class="token punctuation">)</span> <span class="token comment">// 90</span> ngan<span class="token punctuation">.</span><span class="token function">slash</span><span class="token punctuation">(</span>snake<span class="token punctuation">)</span> console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span>snake<span class="token punctuation">.</span>hp<span class="token punctuation">)</span> <span class="token comment">// 50</span> |
Giờ cách chiến binh đã có những skill và tha hồ cà khịa lẫn nhau. Nhưng ở đây, mỗi một chiến binh lại có một skill riêng biệt, nhưng rõ ràng, skill này lại giống hệt nhau. Điều này là lãng phí khi mà ta kiểm tra lại
1 2 3 | harryPotter<span class="token punctuation">.</span>bash <span class="token operator">===</span> ngan<span class="token punctuation">.</span>bash <span class="token comment">// false</span> snake<span class="token punctuation">.</span>bash <span class="token operator">===</span> ngan<span class="token punctuation">.</span>bash <span class="token comment">// false</span> |
Chính vì thể ta cần một cái gì đó giống như constructor, đó chính là prototype
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | <span class="token keyword">function</span> <span class="token function">Warrior</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>hp <span class="token operator">=</span> <span class="token number">100</span> <span class="token punctuation">}</span> Warrior<span class="token punctuation">.</span>prototype<span class="token punctuation">.</span><span class="token function-variable function">bash</span> <span class="token operator">=</span> <span class="token keyword">function</span><span class="token punctuation">(</span>target<span class="token punctuation">)</span> <span class="token punctuation">{</span> target<span class="token punctuation">.</span>hp <span class="token operator">-=</span> <span class="token number">10</span> <span class="token punctuation">}</span> Warrior<span class="token punctuation">.</span>prototype<span class="token punctuation">.</span><span class="token function-variable function">slash</span> <span class="token operator">=</span> <span class="token keyword">function</span><span class="token punctuation">(</span>target<span class="token punctuation">)</span> <span class="token punctuation">{</span> target<span class="token punctuation">.</span>hp <span class="token operator">/=</span> <span class="token number">2</span> <span class="token punctuation">}</span> <span class="token operator">...</span> harryPotter<span class="token punctuation">.</span>bash <span class="token operator">===</span> ngan<span class="token punctuation">.</span>bash <span class="token comment">// true</span> snake<span class="token punctuation">.</span>bash <span class="token operator">===</span> ngan<span class="token punctuation">.</span>bash <span class="token comment">// true</span> |
Cách trên cũng tương tự với cách viết như sau
1 2 3 4 5 6 7 8 9 10 | Warrior<span class="token punctuation">.</span>prototype <span class="token operator">=</span> <span class="token punctuation">{</span> bash<span class="token punctuation">:</span> <span class="token keyword">function</span><span class="token punctuation">(</span>target<span class="token punctuation">)</span> <span class="token punctuation">{</span> target<span class="token punctuation">.</span>hp <span class="token operator">-=</span> <span class="token number">10</span> <span class="token punctuation">}</span><span class="token punctuation">,</span> slash<span class="token punctuation">:</span> <span class="token keyword">function</span><span class="token punctuation">(</span>target<span class="token punctuation">)</span> <span class="token punctuation">{</span> target<span class="token punctuation">.</span>hp <span class="token operator">/=</span> <span class="token number">2</span> <span class="token punctuation">}</span><span class="token punctuation">,</span> <span class="token punctuation">}</span> |
Conclusion
Tuy nhiên với cách này sẽ làm mất đi constructor Warrrior đó nhé.
Trên đây chính là cách mà prototype đã thực hiện khả năng thừa kế và chia sẻ của mình như thế nào trong javascript. Hy vọng các bài tiếp theo mình có thể tiếp tục khám phá nhiều điều thú vị hơn nữa. Cám ơn các bạn đã theo dói
References
https://medium.com/better-programming/the-prototype-pattern-in-javascript-bfe9ff433e6c