การอัปเดตปี 2556 และ 2558 (ดูคำตอบต้นฉบับจาก 2011) ด้านล่าง :
นี้มีการเปลี่ยนแปลงเป็นของ ES2015 (aka "ES6") สเปค: JavaScript ขณะนี้มีผู้รับมอบฉันทะ พร็อกซีช่วยให้คุณสร้างวัตถุที่เป็นพร็อกซีที่แท้จริงสำหรับวัตถุอื่น ๆ นี่คือตัวอย่างง่ายๆที่เปลี่ยนค่าคุณสมบัติใด ๆ ที่เป็นสตริงไปยังตัวพิมพ์ใหญ่ทั้งหมดในการดึงข้อมูล:
"use strict";
if (typeof Proxy == "undefined") {
throw new Error("This browser doesn't support Proxy");
}
let original = {
"foo": "bar"
};
let proxy = new Proxy(original, {
get(target, name, receiver) {
let rv = Reflect.get(target, name, receiver);
if (typeof rv === "string") {
rv = rv.toUpperCase();
}
return rv;
}
});
console.log(`original.foo = ${original.foo}`); // "original.foo = bar"
console.log(`proxy.foo = ${proxy.foo}`); // "proxy.foo = BAR"
การดำเนินการที่คุณไม่ได้แทนที่มีพฤติกรรมเริ่มต้น ในข้างต้นทั้งหมดที่เราแทนที่คือget
มีรายการทั้งหมดของการดำเนินการที่คุณสามารถขอได้
ในget
รายการอาร์กิวเมนต์ของฟังก์ชันตัวจัดการ:
target
เป็นวัตถุที่ถูกพร็อกซี ( original
ในกรณีของเรา)
name
คือ (แน่นอน) ชื่อของคุณสมบัติที่ถูกเรียกคืนซึ่งโดยปกติจะเป็นสตริง แต่อาจเป็นสัญลักษณ์ได้
receiver
เป็นวัตถุที่ควรใช้เช่นเดียวกับthis
ในฟังก์ชั่น getter ถ้าคุณสมบัติเป็น accessor แทนที่จะเป็นคุณสมบัติของข้อมูล ในกรณีปกตินี้เป็นพร็อกซี่หรือสิ่งที่สืบทอดจากมัน แต่มันสามารถReflect.get
เป็นอะไรก็ได้ตั้งแต่ดักอาจถูกเรียกโดย
สิ่งนี้ช่วยให้คุณสร้างวัตถุที่มีคุณสมบัติ getter และ setter แบบ catch-all ที่คุณต้องการ:
"use strict";
if (typeof Proxy == "undefined") {
throw new Error("This browser doesn't support Proxy");
}
let obj = new Proxy({}, {
get(target, name, receiver) {
if (!Reflect.has(target, name)) {
console.log("Getting non-existent property '" + name + "'");
return undefined;
}
return Reflect.get(target, name, receiver);
},
set(target, name, value, receiver) {
if (!Reflect.has(target, name)) {
console.log(`Setting non-existent property '${name}', initial value: ${value}`);
}
return Reflect.set(target, name, value, receiver);
}
});
console.log(`[before] obj.foo = ${obj.foo}`);
obj.foo = "bar";
console.log(`[after] obj.foo = ${obj.foo}`);
ผลลัพธ์ของข้างต้นคือ:
การได้รับทรัพย์สินที่ไม่มีอยู่ 'foo'
[ก่อน] obj.foo = ไม่ได้กำหนด
การตั้งค่าคุณสมบัติที่ไม่มีอยู่ 'foo' ค่าเริ่มต้น: แถบ
[หลังจาก] obj.foo = bar
โปรดสังเกตว่าเราได้รับข้อความ "ไม่มีอยู่จริง" เมื่อเราพยายามดึงข้อมูลfoo
เมื่อยังไม่มีอยู่และอีกครั้งเมื่อเราสร้าง แต่ไม่ใช่หลังจากนั้น
คำตอบจาก 2011 (ดูด้านบนสำหรับการปรับปรุง 2013 และ 2015) :
ไม่จาวาสคริปต์ไม่มีคุณสมบัติที่ดึงดูดทั้งหมด ไวยากรณ์ของ accessor ที่คุณใช้นั้นอยู่ในหัวข้อที่ 11.1.5ของข้อมูลจำเพาะและไม่มีสัญลักษณ์ตัวแทนหรืออะไรทำนองนั้น
แน่นอนคุณสามารถใช้ฟังก์ชั่นที่จะทำ แต่ฉันเดาว่าคุณอาจไม่ต้องการใช้f = obj.prop("foo");
มากกว่าf = obj.foo;
และobj.prop("foo", value);
มากกว่าobj.foo = value;
(ซึ่งจำเป็นสำหรับฟังก์ชันในการจัดการคุณสมบัติที่ไม่รู้จัก)
FWIW, ฟังก์ชั่น getter (ฉันไม่ได้ยุ่งกับ setter logic) จะมีลักษณะเช่นนี้:
MyObject.prototype.prop = function(propName) {
if (propName in this) {
// This object or its prototype already has this property,
// return the existing value.
return this[propName];
}
// ...Catch-all, deal with undefined property here...
};
แต่อีกครั้งฉันไม่สามารถจินตนาการได้ว่าคุณต้องการทำเช่นนั้นเพราะวิธีการเปลี่ยนแปลงวิธีที่คุณใช้วัตถุ