ต่อจากคราวก่อน ครั้งนี้เป็นเรื่องของ prototype วิธีเพิ่มความสามารถให้กับ object
ในภายหลัง
object
ใน Javascript
Object ใน Javascript นั้นเกิดขึ้นได้ 2 วิธี แบบแรก คือการประกาศ Object มาดื้อ ๆ เลย หรือ function ทำการ return ค่าออกมาเป็น Object เช่น
var o1 = {
prop1: 'a',
method1: function () {}
};
var o2 = (function () {
return {
prop1: 'a',
method1: function () {}
};
})();
ส่วนอีกวิธี คือ เกิดจากโอเปอเรอร์ new
กับฟังก์ชั่น
function myClass() {
var a = 5;
function b() {};
this.method1 = b;
}
var o3 = new myClass();
เมื่อใช้ Developer Tool ต่าง ๆ ที่มากับ Web Browser ตรวจสอบค่าของ o1
, o2
, o3
จะพบว่ามีเฉพาะ o3
เท่านั้นที่มี prototype
ติดมาด้วย
การเพิ่มความสามารถของ object
ด้วย prototype
ชื่อหัวข้ออาจจะไม่ถูกต้องเสียเท่าไร แต่จริง ๆ แล้วมันคือ การเพิ่ม method หรือตัวแปรให้กับ Class นั่นเอง ซึ่งในตัวไวยากรณ์ของ Javascript เองนั้น (ก่อน ECMAScript 5) ไม่มี reserved word ของคำนี้ขึ้นมาก่อน และก็ไม่ได้มีไวยากรณ์ที่เกิดมาเพื่อรองรับพฤติกรรมการเขียน Class แบบภาษาอื่นที่เราพบเห็นกัน สิ่งที่ใกล้เคียงที่สุดก็คือการเขียนฟังก์ชั่น ตามตัวอย่าง myClass
นั้น และการใช้ operator this
เพื่อเป็นการระบุว่า method หรือตัวแปรใดจะปรากฎให้ใช้งานได้บน object
ที่เกิดขึ้น
ในกรณีที่เราไม่สามารถไปแก้ไข code บน myClass
ได้ แต่เรามีความต้องการจะเพิ่ม method หรือตัวแปรให้กับ object
ที่เกิดจาก Class นี้ เราสามารถประกาศ properties เพิ่มให้กับ prototype
ของ Class ได้ เช่น
myClass.prototype.method2 = function () {};
หลังจากนั้น o3
ก็จะมี method2
โผล่ขึ้นมาให้เรียกใช้งานได้
เอาไปใช้กับอะไรได้บ้าง
ตัวอย่างรูปแบบที่เห็นการใช้งานที่ดูจาก OOP in JS ก็คือ การทำ Class inheritance นั่นเอง นั่นคือ เรามี Class หลักที่ค่อนข้างเรียบง่าย (เหมือน Class Object
ในภาษาทั่วไป) จากนั้นจึงให้ทุก Class มีแม่เป็น Class Object
นั่นเอง
function myObject() {}
myObject.prototype.method1 = function() {};
function table() {}
// Sequence matter!
table.prototype = new myObject();
table.prototype.constructor = table;
table.prototype.method2 = function() {};
table.prototype.method1 = function() { myObject.prototype.method1.call(this); };
สังเกตว่ามี prototype.constructor
ด้วย ซึ่งบรรทัดนั้นเป็นการสั่งให้ table ใช้ constructor ของตัวเอง ไม่ไปใช้ของ myObject และ call
ที่ใช้กับการ override method1
ใน Javascript นั้นไม่มีเรื่อง Parent class ตรง ๆ (แต่ดันมี super
เป็นคำสงวน) ดังนั้นเราก็สามารถใช้ prototype นี้เป็นตัวนิยามเรื่องนี้ได้ เช่น
table.prototype.parentClass = myObject.prototype;
ทำให้สามารถนิยาม method1 ใน table ซึ่งรับมาจาก myObject ได้เป็น
table.prototype.method1 = function() { this.parentClass.method1.call(this); }
มึนดีไหมล่ะ?