จาก ES3 สู่ ES5
เนื้อหาตั้งแต่บทนี้ไปจะเป็นคำสั่งและวิธีเขียนที่ใช้ได้ตั้งแต่จาวาสคริปต์รุ่น
ES5 ขึ้นไป นั่นคือถ้าใครจะเขียนจาวาสคริปต์เพื่อใช้ใน extendscript ของ adobe
หรือโปรแกรมใดๆที่ใช้ ES3 เป็นพื้นฐานจะไม่สามารถใช้คำสั่งต่อไปนี้ได้
ES3 นั้นออกมาตั้งแต่ปี 1999 ซึ่งก็นานแล้ว
หลังจากนั้นก็ไม่ได้มีความเปลี่ยนแปลงอะไรมากนัก จนมาถึง ES5 ในปี 2009 (ไม่มี
ES4 จาก 3 โดดไป 5 เลย) ก็มีการเพิ่มความสามารถใหม่เข้ามาส่วนหนึ่ง
แม้ว่าจะไม่ได้เยอะเท่ากับที่เพิ่มจาก ES5 ไปเป็นใน ES6 ตอนปี 2015
ความสามารถหลักๆที่เพิ่มเข้ามาได้แก่
- การจำกัดความเปลี่ยนแปลงของออบเจ็กต์ (บทนี้)
- การสร้างและกำหนดรายละเอียดพรอเพอร์ตีในออบเจ็กต์ (
บทที่ ๒๖)
- เมธอด Object.getPrototypeOf สำหรับสำหรับหาโพรโทไทป์ของออบเจ็กต์ (บทที่ ๒๖)
- เมธอดต่างๆสำหรับไล่จัดการค่าในแถวลำดับ เช่น .map, .filter, .reduce, ฯลฯ (
บทที่ ๒๗)
- มีออบเจ็กต์ JSON ซึ่งใช้การจัดการกับข้อมูล json (
บทที่ ๒๘)
- การใช้ use strict เปิดโหมดเคร่งครัด (บทที่ ๒๙)
- เมธอด trim สำหรับตัดช่องว่างหัวท้ายสายอักขระ (บทที่ ๒๙)
- เมธอด indexOf กับ lastIndexOf สามารถใช้ในแถวลำดับได้ (บทที่ ๒๙)
การแช่แข็งออบเจ็กต์
ปกติออบเจ็กต์เมื่อสร้างขึ้นมาแล้วสามารถเปลี่ยนแปลงค่าพรอเพอร์ตีต่างๆได้อย่างอิสระ
คือแก้ค่าพรอเพอร์ตีที่มีอยู่ได้ เพิ่มพรอเพอร์ตีใหม่ได้
หรือลบพรอเพอร์ตีที่มีอยู่ได้
แต่หากเราต้องการให้ออบเจ็กต์นั้นไม่สามารถทำการเปลี่ยนแปลงอะไรได้อีก
ก็สามารถทำได้โดยการใช้ฟังก์ชันต่างๆซึ่งใช้จัดการสร้างข้อจำกัดความเปลี่ยนแปลงให้ออบเจ็กต์
คำสั่งต่างๆนั้นอยู่ในออบเจ็กต์ Object ได้แก่ Object.preventExtensions,
Object.seal และ Object.freeze
อย่างแรกคือ Object.freeze
ใช้เมื่อต้องการแช่ออบเจ็กต์ไว้ไม่ให้ทำการเปลี่ยนแปลงใดๆได้เลย
ออบเจ็กต์ที่ถูกแช่ไว้จะไม่สามารถแก้ค่าพรอเพอร์ตีได้
ไม่สามารถเพิ่มพรอเพอร์ตีใหม่ หรือลบพรอเพอร์ตีที่มีอยู่ได้
var katomnam = {
khwamchu: 1500,
unhaphum: 80
};
Object.freeze(katomnam);
katomnam.unhaphum = 100; // แก้ค่า (ไม่สำเร็จ)
alert(katomnam.unhaphum); // ได้ 80
delete katomnam.khwamchu; // ลบทิ้ง (ไม่สำเร็จ)
alert(katomnam.khwamchu); // ได้ 1500
katomnam.pH = 7; // เพิ่มพรอเพอร์ตีใหม่ (ไม่สำเร็จ)
alert(katomnam.pH); // ได้ undefined
การผนึกออบเจ็กต์
หากแค่ต้องการไม่ให้มีการใส่เพิ่มพรอเพอร์ตีใหม่หรือลบพรอเพอร์ตีที่มีอยู่เดิม
แต่สามารถแก้ไขค่าในพรอเพอร์ตีที่มีอยู่ได้ อาจใช้ฟังก์ชัน Object.seal
แทนที่จะใช้ Object.freeze
var katomnam = {
khwamchu: 1500,
unhaphum: 80
};
Object.seal(katomnam);
katomnam.unhaphum = 100; // แก้ค่า (สำเร็จ)
alert(katomnam.unhaphum); // ได้ 100
delete katomnam.khwamchu; // ลบทิ้ง (ไม่สำเร็จ)
alert(katomnam.khwamchu); // ได้ 1500
katomnam.pH = 7; // เพิ่มพรอเพอร์ตีใหม่ (ไม่สำเร็จ)
alert(katomnam.pH); // ได้ undefined
การทำให้ออบเจ็กต์เพิ่มพรอเพอร์ตีใหม่ไม่ได้
หากแค่ต้องการไม่ให้มีการใส่เพิ่มพรอเพอร์ตีใหม่
แต่สามารถแก้ไขค่าหรือลบพรอเพอร์ตีที่มีอยู่ได้ อาจใช้ฟังก์ชัน
Object.preventExtensions
var katomnam = {
khwamchu: 1500,
unhaphum: 80
};
Object.preventExtensions(katomnam);
katomnam.unhaphum = 100; // แก้ค่า (สำเร็จ)
alert(katomnam.unhaphum); // ได้ 100
delete katomnam.khwamchu; // ลบทิ้ง (สำเร็จ)
alert(katomnam.khwamchu); // ได้ undefined
katomnam.pH = 7; // เพิ่มพรอเพอร์ตีใหม่ (ไม่สำเร็จ)
alert(katomnam.pH); // ได้ undefined
การตรวจสอบว่าออบเจ็กต์ถูกตั้งข้อจำกัดอะไรไว้บ้าง
การตรวจสอบว่าออบเจ็กต์ถูกจำกัดความเปลี่ยนแปลงไว้หรือไม่ ทำได้โดยใช้ฟังก์ชัน
Object.isExtensible Object.isSealed Object.isFrozen
Object.isExtensible จะตรวจสอบว่าออบเจ็กต์สามารถขยายได้หรือไม่ ถ้ามีการใช้
Object.preventExtensions ไว้ก็จะขยายไม่ได้จึงได้ false
Object.isSealed จะตรวจสอบว่าถูกผนึกไว้หรือเปล่า ถ้าใช่ก็จะได้ true
Object.isFrozen จะตรวจสอบว่าถูกผนึกไว้หรือเปล่า ถ้าใช่ก็จะได้ true
ลองดูตัวอย่างทีละกรณี
กรณีที่ออบเจ็กต์โดน freeze ไว้
var obj = { a: 1 };
Object.freeze(obj);
alert(Object.isExtensible(obj)); // ได้ false
alert(Object.isSealed(obj)); // ได้ true
alert(Object.isFrozen(obj)); // ได้ true
กรณีที่แค่โดน seal
var obj = { b: 1 };
Object.seal(obj);
alert(Object.isExtensible(obj)); // ได้ false
alert(Object.isSealed(obj)); // ได้ true
alert(Object.isFrozen(obj)); // ได้ false
กรณีที่แค่ใช้ Object.preventExtensions
var obj = { c: 1 };
Object.preventExtensions(obj);
alert(Object.isExtensible(obj)); // ได้ false
alert(Object.isSealed(obj)); // ได้ false
alert(Object.isFrozen(obj)); // ได้ false
แต่หากออบเจ็กต์นั้นไม่มีพรอเพอร์ตีอยู่เลย แค่ใช้ Object.preventExtensions
ก็เหมือนใช้ freeze แล้ว
var obj = {};
Object.preventExtensions(obj);
alert(Object.isExtensible(obj)); // ได้ false
alert(Object.isSealed(obj)); // ได้ true
alert(Object.isFrozen(obj)); // ได้ true
สรุปข้อจำกัดความเปลี่ยนแปลงของออบเจ็กต์
สรุปฟังก์ชันสำหรับจำกัดความเปลี่ยนแปลงทั้ง ๓ ตัวได้ดังนี้
|
preventExtension |
seal |
freeze |
เพิ่มพรอเพอร์ตี |
ไม่ได้ |
ไม่ได้ |
ไม่ได้ |
ลบพรอเพอร์ตี |
ได้ |
ไม่ได้ |
ไม่ได้ |
แก้ค่าพรอเพอร์ตี |
ได้ |
ได้ |
ไม่ได้ |
ข้อจำกัดไม่ได้รวมไปถึงออบเจ็กต์ด้านใน
จะเห็นว่าคำสั่งต่างๆที่กล่าวมาทำให้พรอเพอร์ตีในออบเจ็กต์ไม่มีการเปลี่ยนแปลงได้
อย่างไรก็ตาม หากพรอเพอร์ตีในออบเจ็กต์นั้นก็เป็นออบเจ็กต์ด้วย
ตัวพรอเพอร์ตีที่เป็นออบเจ็กต์นั้นก็ยังทำการเปลี่ยนแปลงได้อยู่แม้ว่าออบเจ็กต์ตัวนอกจะถูกตั้งข้อจำกัดก็ตาม
ไม่ได้รับผลไปด้วย
ตัวอย่างเช่น
var objNok = { objNai: {} };
Object.freeze(objNok);
objNok.objNai.prop = "xxx";
alert(objNok.objNai.prop); // ได้ xxx
ฉะนั้นแล้ว หากต้องการจะจำกัดการเปลี่ยนแปลงทั้งหมดก็ต้องใช้ Object.freeze
กับออบเจ็กต์ด้านในไปด้วย
Object.freeze(objNok.objNai);
objNok.objNai.prop = "yyy";
alert(objNok.objNai.prop); // ได้ xxx
ดังนั้นจึงต้องระวังตรงนี้ด้วย เวลาที่ใช้กับออบเจ็กต์ที่พรอเพอร์ตีเป็นออบเจ็กต์