Attribute Descriptor เป็นแนวคิดใหม่ที่เพิ่มเข้ามาใน ES5 และฟังก์ชั่นของมันคือการเพิ่มการควบคุมเพิ่มเติมให้กับคุณสมบัติของวัตถุ
Object.defineProperty
ในการศึกษาตัวบ่งชี้แอตทริบิวต์เราต้องพูดคุยเกี่ยวกับวิธีการของ Object.defineProperty ก่อน วัตถุประสงค์ของวิธีนี้คือการกำหนดคุณสมบัติใหม่สำหรับวัตถุหรือแก้ไขคุณสมบัติที่มีอยู่ ต้นแบบมีดังนี้:
การคัดลอกรหัสมีดังนี้:
Object.defineProperty (obj, prop, descriptor)
ตัวอย่างการใช้งาน:
การคัดลอกรหัสมีดังนี้:
var obj = {};
Object.defineProperty (obj, 'attr', {value: 1});
รหัสข้างต้นเพิ่มแอตทริบิวต์ชื่อ attr ไปยังวัตถุ OBJ ด้วยค่า 1 เทียบเท่ากับ:
การคัดลอกรหัสมีดังนี้:
var obj = {};
obj.attr = 1;
ในการเปรียบเทียบการเขียน Object.DefineProperty ดูเหมือนจะซับซ้อนกว่า อย่างไรก็ตามความลับที่ใหญ่ที่สุดของมันอยู่ในพารามิเตอร์ที่สาม
data descriptor
สมมติว่าเราต้องการให้ Att เป็นแอตทริบิวต์แบบอ่านอย่างเดียวเราสามารถเพิ่ม Data Descriptor ที่เขียนได้:
การคัดลอกรหัสมีดังนี้:
var obj = {};
Object.defineProperty (obj, 'attr', {
ค่า: 1,
เขียนได้: เท็จ
-
console.log (obj.attr);
obj.attr = 2; // ล้มเหลว
console.log (obj.attr);
ดำเนินการโปรแกรมข้างต้นและคุณจะพบว่าค่าของ Attt ที่พิมพ์ออกมาสองครั้งคือ 1 ซึ่งหมายความว่าการเขียนแอตทริบิวต์ล้มเหลว อย่างไรก็ตามผลลัพธ์นี้จะอธิบายไม่ได้เล็กน้อยเนื่องจากการดำเนินการของคำสั่งการมอบหมายไม่มีข้อยกเว้นใด ๆ แต่มันล้มเหลว แค่คิดว่าหากปัญหาดังกล่าวเกิดขึ้นในรหัสบล็อกบัสเตอร์มันจะยากที่จะแก้ไขปัญหา ในความเป็นจริงตราบใดที่รหัสทำงานในโหมดที่เข้มงวดจะมีการสร้างข้อยกเว้น:
การคัดลอกรหัสมีดังนี้:
'ใช้อย่างเข้มงวด'; // เข้าสู่โหมดที่เข้มงวด
var obj = {};
Object.defineProperty (obj, 'attr', {
ค่า: 1,
เขียนได้: เท็จ
-
obj.attr = 2; // โยนข้อยกเว้น
ลองดูที่ตัวบ่งชี้ข้อมูลอื่นที่ระบุได้ซึ่งสามารถควบคุมได้ว่าแอตทริบิวต์สามารถแจกแจงได้หรือไม่ หากคุณเพียงกำหนดคุณสมบัติคุณสมบัตินี้สามารถระบุได้ในสำหรับ ... ในลูป:
การคัดลอกรหัสมีดังนี้:
var obj = {};
obj.attr = 1;
สำหรับ (var i ใน obj) {console.log (obj [i]); -
สำรองสามารถ "ซ่อน" ได้:
var obj = {};
Object.defineProperty (obj, 'attr', {
ค่า: 1,
enumerable: FALSE
-
สำหรับ (var i ใน obj) {console.log (obj [i]); -
ดำเนินการรหัสด้านบนและคุณจะพบว่าคอนโซลส่งออกอะไรเพราะแอตทริบิวต์ไม่สามารถระบุได้ในเวลานี้
ต้องบอกว่าคุณอาจมีคำถาม: ตัวบ่งชี้แอตทริบิวต์สามารถแก้ไขได้หรือไม่? ตัวอย่างเช่นคุณสมบัติการอ่านอย่างเดียวสามารถกำหนดเป็นเขียนได้อีกครั้งหรือไม่? ที่จริงแล้วสิ่งนี้ขึ้นอยู่กับตัวบ่งชี้ข้อมูลอื่นที่กำหนดค่าได้ซึ่งสามารถควบคุมได้ว่าตัวอธิบายแอตทริบิวต์สามารถเปลี่ยนแปลงได้หรือไม่
การคัดลอกรหัสมีดังนี้:
var obj = {};
Object.defineProperty (obj, 'attr', {
ค่า: 1,
เขียนได้: เท็จ
สามารถกำหนดค่าได้: จริง
-
Object.defineProperty (obj, 'attr', {
เขียนได้: จริง
-
obj.attr = 2;
รหัสด้านบนแรกกำหนด ATTR เป็นแอตทริบิวต์แบบอ่านอย่างเดียวจากนั้นนิยามใหม่เป็นงานเขียน ดังนั้นการเขียนถึง Att ก็ประสบความสำเร็จ
เข้าถึง descriptor
ตัวบ่งชี้การเข้าถึงนั้นคล้ายกับ Accessor Get/Set ในวัตถุที่มุ่งเน้น
การคัดลอกรหัสมีดังนี้:
var obj = {};
Object.defineProperty (obj, 'attr', {
ชุด: ฟังก์ชัน (val) {this._attr = math.max (0, val); -
รับ: function () {return this._attr; -
-
obj.attr = -1;
console.log (obj.attr); // 0
ในรหัสข้างต้นการเข้าถึง ATTT จะเข้าถึง _ATTR จริง ๆ และค่าต่ำสุดถูก จำกัด ไว้ที่ 0 ในฟังก์ชันชุด
รับแอตทริบิวต์ descriptor
ตัวอธิบายแอตทริบิวต์การตั้งค่าทั้งหมดดังกล่าวข้างต้นดังนั้นจะรับคำอธิบายที่ตั้งไว้ได้อย่างไร? Object.getownPropertyDescriptor สามารถทำได้
การคัดลอกรหัสมีดังนี้:
var obj = {};
Object.defineProperty (obj, 'attr', {
ค่า: 1,
เขียนได้: เท็จ
สามารถกำหนดค่าได้: จริง
-
var desc = object.getownpropertydescriptor (obj, 'attr');
console.dir (desc);
การควบคุมวัตถุ
Object.defineProperty ที่กล่าวถึงก่อนหน้านี้ดำเนินการกับคุณสมบัติของวัตถุในขณะที่ทั้งสามวิธีที่กล่าวถึงด้านล่างทำงานโดยตรงบนวัตถุ
Object.preventExtensions สามารถป้องกันวัตถุจากการมีคุณสมบัติใหม่:
การคัดลอกรหัสมีดังนี้:
var obj = {};
obj.attr = 1;
Object.preventExtensions (OBJ);
obj.attr2 = 2; //ล้มเหลว
Object.Seal สามารถสร้างค่าคุณสมบัติของวัตถุเท่านั้นที่จะแก้ไข (หากคุณสมบัติเป็นแบบอ่านอย่างเดียวแม้แต่ค่าคุณสมบัติไม่สามารถแก้ไขได้):
การคัดลอกรหัสมีดังนี้:
var obj = {};
obj.attr = 1;
Object.seal (OBJ);
obj.attr = 1.5;
ลบ obj.attr; // ล้มเหลว
Object.freeze สามารถทำให้วัตถุไม่ได้แก้ไขอย่างสมบูรณ์:
การคัดลอกรหัสมีดังนี้:
var obj = {};
obj.attr = 1;
Object.freeze (obj);
obj.attr = 1.5; // ล้มเหลว
obj.attr2 = 2; //ล้มเหลว
จากนั้นคุณอาจถามอีกครั้งคุณจะรู้ได้อย่างไรว่าวัตถุได้รับการป้องกันส่วนขยายปิดผนึกหรือแช่แข็ง? คำตอบคือการโทรหา Object.isextensible, Object.isseled และ Object.isfrozen ตามลำดับ การใช้ฟังก์ชั่นทั้งสามนี้ค่อนข้างง่ายและไม่ยุ่งยากอีกต่อไป
โดยทั่วไปวัตถุสามารถควบคุมได้อย่างเคร่งครัดผ่านตัวบ่งชี้แอตทริบิวต์และความเข้มงวดของตรรกะของโปรแกรมมีความเข้มแข็ง ข้อเสียอย่างเดียวคือ ES5 ถูกนำไปใช้ใน IE9 (IE9 ยังไม่รองรับโหมดที่เข้มงวด) เมื่อพิจารณาว่าส่วนแบ่ง IE8 ในประเทศยังคงค่อนข้างสูงชุดของสิ่งนี้สามารถใช้ในเบราว์เซอร์มือถือและ Node.js