Pembaruan 2013 dan 2015 (lihat di bawah untuk jawaban asli dari 2011) :
Ini berubah pada spesifikasi ES2015 (alias "ES6"): JavaScript sekarang memiliki proxy . Proxy memungkinkan Anda membuat objek yang benar-benar proxy untuk (fasad) objek lain. Berikut adalah contoh sederhana yang mengubah nilai properti apa pun yang merupakan string ke semua batas saat pengambilan:
"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"
Operasi yang tidak Anda timpa memiliki perilaku default. Di atas, semua yang kami timpa adalah get
, tetapi ada seluruh daftar operasi yang dapat Anda lakukan.
Dalam get
daftar argumen fungsi pawang:
target
adalah objek yang sedang diproksikan ( original
, dalam kasus kami).
name
adalah (tentu saja) nama properti yang diambil, yang biasanya berupa string tetapi juga bisa menjadi Simbol.
receiver
adalah objek yang harus digunakan seperti this
pada fungsi pengambil jika properti adalah accessor daripada properti data. Dalam kasus normal ini adalah proksi atau sesuatu yang mewarisi darinya, tetapi bisa berupa apa saja karena perangkap mungkin dipicu oleh Reflect.get
.
Ini memungkinkan Anda membuat objek dengan fitur catch-all getter dan setter yang Anda inginkan:
"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}`);
Output di atas adalah:
Mendapatkan properti 'foo' yang tidak ada
[sebelum] obj.foo = tidak ditentukan
Mengatur properti 'foo' yang tidak ada, nilai awal: bilah
[setelah] obj.foo = bar
Perhatikan bagaimana kita mendapatkan pesan "tidak ada" ketika kita mencoba mengambilnya foo
ketika belum ada, dan lagi ketika kita membuatnya, tetapi tidak setelah itu.
Jawaban dari 2011 (lihat pembaruan di atas untuk 2013 dan 2015) :
Tidak, JavaScript tidak memiliki fitur properti tangkap semua. Sintaks accessor yang Anda gunakan tercakup dalam Bagian 11.1.5 dari spesifikasi, dan tidak menawarkan wildcard atau sesuatu seperti itu.
Anda tentu saja dapat mengimplementasikan fungsi untuk melakukannya, tetapi saya rasa Anda mungkin tidak ingin menggunakan f = obj.prop("foo");
daripada f = obj.foo;
dan obj.prop("foo", value);
bukannya obj.foo = value;
(yang akan diperlukan untuk fungsi untuk menangani properti yang tidak diketahui).
FWIW, fungsi pengambil (saya tidak repot-repot dengan logika setter) akan terlihat seperti ini:
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...
};
Tetapi sekali lagi, saya tidak bisa membayangkan Anda benar-benar ingin melakukan itu, karena cara itu mengubah cara Anda menggunakan objek.