การโต้ตอบส่วนใหญ่ระหว่างคุณกับพร็อพเพอร์ตี้ออบเจ็กต์มักจะ ระดับพื้นผิว รวมถึงการสร้างลิเทอรัลวัตถุและการตั้งค่าและการเข้าถึง ค่าพร็อพเพอร์ตี้โดยใช้คีย์ แต่คุณสามารถกำหนดค่าพร็อพเพอร์ตี้ใดๆ สำหรับการควบคุมโดยละเอียดเกี่ยวกับวิธีเข้าถึงพร็อพเพอร์ตี้เหล่านั้น เปลี่ยนแปลงและนิยาม พร็อพเพอร์ตี้ออบเจ็กต์ทุกรายการมีชุดแอตทริบิวต์ที่มองไม่เห็น ซึ่งมีข้อมูลเมตาที่เชื่อมโยงกับพร็อพเพอร์ตี้นั้น ซึ่งเรียกว่า "พร็อพเพอร์ตี้ ข้อบ่งชี้"
พร็อพเพอร์ตี้ใดๆ ก็ตามมีข้อบ่งชี้ 2 ประเภทดังนี้ ข้อบ่งชี้ข้อมูลและข้อบ่งชี้เครื่องมือเข้าถึง โดยข้อบ่งชี้ข้อมูลประกอบด้วย คู่คีย์และค่าที่มีค่าของพร็อพเพอร์ตี้ โดยไม่คำนึงว่า สามารถเขียนได้ กำหนดค่า หรือแจกแจงได้ ตัวบ่งชี้ตัวเข้าถึงประกอบด้วย ที่ดำเนินการเมื่อมีการตั้งค่า เปลี่ยนแปลง หรือเข้าถึงพร็อพเพอร์ตี้
พร็อพเพอร์ตี้ | ประเภทข้อบ่งชี้ | ค่าเริ่มต้นจาก Object.defineProperty() |
คำอธิบาย |
---|---|---|---|
[[Value]] |
ข้อมูล | undefined |
มีค่าของพร็อพเพอร์ตี้ |
[[Writable]] |
ข้อมูล | false |
กำหนดว่าคุณสามารถเปลี่ยนค่าของพร็อพเพอร์ตี้ได้หรือไม่ |
[[Get]] |
ผู้เข้าถึง | undefined |
ฟังก์ชัน getter ของพร็อพเพอร์ตี้ ซึ่งจะทำงานเมื่อฟังก์ชัน มีการเข้าถึงพร็อพเพอร์ตี้ |
[[Set]] |
ผู้เข้าถึง | undefined |
ฟังก์ชัน setter ของพร็อพเพอร์ตี้ ซึ่งจะทำงานเมื่อฟังก์ชัน มีการตั้งค่าหรือเปลี่ยนแปลงพร็อพเพอร์ตี้ |
[[Configurable]] |
ทั้งคู่ | false |
หากนี่คือ false คุณจะลบพร็อพเพอร์ตี้และ
ไม่สามารถเปลี่ยนแอตทริบิวต์ได้ หากนี่คือ false และ
[[Writable]] เท่ากับ true ค่าของพร็อพเพอร์ตี้สามารถ
จะยังคงมีการเปลี่ยนแปลง |
[[Enumerable]] |
ทั้งคู่ | false |
หากเป็น true คุณสามารถทำซ้ำพร็อพเพอร์ตี้โดยใช้
for...in ลูป หรือ Object.keys() คงที่
|
พร็อพเพอร์ตี้แต่ละรายการเหล่านี้ใช้ชวเลขเดียวกับ [[Prototype]]
เพื่อบ่งบอกว่า
พร็อพเพอร์ตี้เหล่านี้ไม่ได้มีไว้เพื่อเข้าถึงโดยตรง ให้ใช้
Object.defineProperty()
เมธอดแบบคงที่เพื่อกำหนดหรือแก้ไขคุณสมบัติของพร็อพเพอร์ตี้
ออบเจ็กต์ Object.defineProperty()
ยอมรับอาร์กิวเมนต์ 3 ตัว ได้แก่ ออบเจ็กต์ที่จะดำเนินการ
คีย์พร็อพเพอร์ตี้ที่จะสร้างหรือแก้ไข และออบเจ็กต์ที่มี
ข้อบ่งชี้ที่เชื่อมโยงกับพร็อพเพอร์ตี้ที่กำลังสร้างหรือแก้ไข
โดยค่าเริ่มต้น พร็อพเพอร์ตี้ที่สร้างขึ้นโดยใช้ Object.defineProperty()
ไม่สามารถเขียน แจกแจง หรือกำหนดค่าได้ แต่พร็อพเพอร์ตี้ที่คุณสร้าง
เป็นส่วนหนึ่งของอ็อบเจ็กต์ลิเทอรัล หรือใช้สัญลักษณ์จุดหรือวงเล็บเป็น
สามารถเขียนได้ สามารถแจกแจงได้ และกำหนดค่าได้
const myObj = {};
Object.defineProperty(myObj, 'myProperty', {
value: true,
writable: false
});
myObj.myProperty;
> true
myObj.myProperty = false;
myObj.myProperty;
> true
ตัวอย่างเช่น เมื่อ [[Writable]]
มีค่า false
ให้พยายามตั้งค่าใหม่
สำหรับพร็อพเพอร์ตี้ที่เกี่ยวข้องไม่ทำงานนอกโหมดเข้มงวดโดยไม่มีการแจ้งเตือน และมีการส่ง
ข้อผิดพลาดในโหมดเข้มงวด:
{
const myObj = {};
Object.defineProperty(myObj, 'myProperty', {
value: true,
writable: false
});
myObj.myProperty = false;
myObj.myProperty;
}
> true
(function () {
"use strict";
const myObj = {};
Object.defineProperty(myObj, 'myProperty', {
value: true,
writable: false
});
myObj.myProperty = false;
myObj.myProperty;
}());\
> Uncaught TypeError: "myProperty" is read-only
การใช้ข้อบ่งชี้อย่างมีประสิทธิภาพเป็นแนวคิดที่ค่อนข้างขั้นสูง แต่
การทำความเข้าใจโครงสร้างภายในของวัตถุ
จำเป็นต่อการทำความเข้าใจ
ไวยากรณ์ที่เกี่ยวข้องกับการทำงานกับออบเจ็กต์ด้วยวิธีทั่วไป ตัวอย่างเช่น
แนวคิดเหล่านี้จะนำมาใช้เมื่อใช้เมธอด Object.create()
แบบคงที่
ซึ่งช่วยให้คุณสามารถควบคุมต้นแบบที่แนบกับ
ออบเจ็กต์
Object.create()
สร้างออบเจ็กต์ใหม่โดยใช้ออบเจ็กต์ที่มีอยู่เป็น
ต้นแบบ ซึ่งจะช่วยให้วัตถุใหม่รับคุณสมบัติและเมธอดมาจากอีกรายการได้
ออบเจ็กต์ที่ผู้ใช้กำหนดในลักษณะเดียวกับที่ออบเจ็กต์สืบทอดพร็อพเพอร์ตี้
ต้นแบบ Object
ในตัวของ JavaScript เมื่อคุณเรียกใช้ Object.create()
ด้วย
เป็นอาร์กิวเมนต์ โดยสร้างวัตถุว่างที่มีอ็อบเจ็กต์ที่ส่งผ่าน
เครื่องต้นแบบ
const myCustomPrototype = {
'myInheritedProp': 10
};
const newObject = Object.create( myCustomPrototype );
newObject;
> Object { }
<prototype>: Object { myInheritedProp: 10 }
myInheritedProp: 10
<prototype>: Object { … }
Object.create
สามารถใช้อาร์กิวเมนต์ที่ 2 ที่ระบุพร็อพเพอร์ตี้ของตนเองสำหรับ
ออบเจ็กต์ที่สร้างขึ้นใหม่โดยใช้ไวยากรณ์ที่คล้ายกับ Object.defineProperty()
—
ซึ่งก็คือคีย์การแมปออบเจ็กต์กับชุดแอตทริบิวต์ข้อบ่งชี้
const myCustomPrototype = {
'myInheritedProp': 10
};
const myObj = Object.create( myCustomPrototype, {
myProperty: {
value: "The new property value.",
writable: true,
configurable: true
}
});
myObj;
> Object { … }
myProperty: "The new property value."
<prototype>: Object { myInheritedProp: 10 }
ในตัวอย่างนี้ ออบเจ็กต์ใหม่ (myObj
) ใช้ออบเจ็กต์ลิเทอรัล
(myCustomPrototype
) เป็นต้นแบบ ซึ่งในตัวเองจะมีโค้ดที่รับช่วงมา
Object.prototype
ส่งผลให้เกิดชุดต้นแบบที่รับช่วงมาซึ่งเรียกว่า
เชนต้นแบบ แต่ละออบเจ็กต์มีต้นแบบ ไม่ว่าจะได้รับการมอบหมายหรือรับค่ามา
ซึ่งมีต้นแบบของตัวเองหรือที่รับช่วงมา เชนนี้สิ้นสุดที่เวลา
null
ซึ่งไม่มีต้นแบบของตัวเอง
const myPrototype = {
'protoProp': 10
};
const newObject = Object.setPrototypeOf( { 'objProp' : true }, myPrototype );
newObject;
> Object { objProp: true }
objProp: true
<prototype>: Object { protoProp: 10 }
protoProp: 10
<prototype>: Object { … }
พร็อพเพอร์ตี้ที่อยู่ในต้นแบบของค่าจะอยู่ใน "ระดับบนสุด" ของออบเจ็กต์ได้โดยไม่จำเป็นต้องเข้าถึงพร็อพเพอร์ตี้ต้นแบบโดยตรง
const objectLiteral = {
"value" : true
};
objectLiteral;
> Object { value: true }
value: true
<prototype>: Object { … }
objectLiteral.toString();
"[object Object]"
รูปแบบนี้ยังคงใช้ได้กับห่วงโซ่ต้นแบบทั้งหมดที่เชื่อมโยงกับ : เมื่อพยายามเข้าถึงพร็อพเพอร์ตี้ ล่ามจะมองหาสิ่งนั้น พร็อพเพอร์ตี้ในแต่ละ "ระดับ" ของห่วงโซ่ต้นแบบ จากบนลงล่างจนถึง ค้นหาอสังหาริมทรัพย์หรือห่วงโซ่สิ้นสุด:
const myCustomPrototype = {
'protoProp': "Prototype property value."
};
const myObj = Object.create( myCustomPrototype, {
myProperty: {
value: "Top-level property value.",
writable: true,
configurable: true
}
});
myObj.protoProp;
> "Prototype property value."
ตรวจสอบความเข้าใจ
ตัวบ่งชี้ใดคือตัวเข้าถึง
[[Get]]
[[Set]]
[[Writable]]