Class ใน JavaScript, Class กับ Constructor

  • ชื่อของ Contructor จะให้เริ่มต้นด้วยอักษรตัวใหญ่
  • เรียกใช้ด้วย new 
  • prototype property จะเป็น prototype ของ object ที่สร้างขึ้นใหม่
  • ค่า new.target จะเป็น undefined ถ้ามีการเรียกใช้ construtor แบบ function ธรรมดา
  • ถ้าใช้ new ค่า new.target จะเป็น constuctor function ของ class หรือ subclass ที่เรียกใช้
  • ใน ES6 จะมี keyword class ให้ใช้

// This is a factory function that returns a new range object.
function range(from, to) {
    // Use Object.create() to create an object that inherits from the
    // prototype object defined below.  The prototype object is stored as
    // a property of this function, and defines the shared methods (behavior)
    // for all range objects.
    let r = Object.create(range.methods);
    // Store the start and end points (state) of this new range object.
    // These are noninherited properties that are unique to this object.
    r.from = from;
    r.to = to;
    // Finally return the new object
    return r;
}
// This prototype object defines methods inherited by all range objects.
range.methods = {
    // Return true if x is in the range, false otherwise
    // This method works for textual and Date ranges as well as numeric.
	    includes(x) { return this.from <= x && x <= this.to; },
    // A generator function that makes instances of the class iterable.
    // Note that it only works for numeric ranges.
    *[Symbol.iterator]() {
        for(let x = Math.ceil(this.from); x <= this.to; x++) yield x;
    },
    // Return a string representation of the range
    toString() { return "(" + this.from + "..." + this.to + ")"; }
};
// Here are example uses of a range object.
let r = range(1,3);      // Create a range object
r.includes(2)            // => true: 2 is in the range
r.toString()             // => "(1...3)"
[...r]                   // => [1, 2, 3]; convert to an array via iterator

Constructor การระบุ Class , และ instanceof

Class ของ object จะขึ้นอยู่กับ prototype object เป็นหลัก object ที่มี prototype เดียวกันก็จะเป็น object ใน class เดียวกัน ถึงแม้จะสร้างมาจาก contructor function คนละ function กันก็ตาม

แต่โดยทั่วไปจะกำหนดให้ชื่อของ constructor function เป็นชื่อของ class 
ชื่อของ construtor ยังถูกใช้ร่วมกับ instanceof

r instanceof Range   // => true: r inherits from Range.prototype

instanceof จะเช็คว่า prototype ของ object เป็น object เดียวกับ prototype ของ construtor  หรือไม่และจะคืนค่าเป็น true ถ้าทั้งคู่เป็น object เดียวกันถึงแม้ว่าอาจจะสร้างมาจาก constructor คนละตัวกันก็ตาม

อีกวิธีของการทดสอบ class คือการใช้ isPrototypeOf()

range.methods.isPrototypeOf(r);  // range.methods is the prototype object.

constructor property

ใน JavaScript ทุก function จะสามารถถูกเรียกใช้เป็น constructor ได้ และจะมี property  prototype โดยอัตโนมัต และใน prototype จะมี property ชื่อว่า constructor อยู่ ซึ่งจะเป็นตัว function นั้นๆนั่นเอง

let F = function() {};
F.prototype.constructor === F  // => true: F.prototype.constructor === F for any F

การสร้าง object prototype ขึ้นมาใหม่จะทำให้ property constructor นี้หายไป แก้ไขได้ด้วยการเพื่มเข้าไปในโค้ดดังนี้

Range.prototype = {
    constructor: Range,  // Explicitly set the constructor back-reference
    /* method definitions go here */
};

หรือแทนที่จะสร้าง object ใหม่ ให้เพิ่ม property เข้าไปใน object เดิมแทน
// Extend the predefined Range.prototype object so we don't overwrite
// the automatically created Range.prototype.constructor property.
Range.prototype.includes = function(x) {
    return this.from <= x && x <= this.to;
};
Range.prototype.toString = function() {
    return "(" + this.from + "..." + this.to + ")";
};

Comments

Popular posts from this blog

15.8.4 การวาดลงบน cavas

15.8.3 Graphics Attributes

Class ใน JavaScript, การสร้าง class ด้วย keyword class