Javascript: Prototype การงอกเงยของ function

ต่อจากคราวก่อน ครั้งนี้เป็นเรื่องของ 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); }

มึนดีไหมล่ะ?

Blog Tags: 

Add new comment