Aggiornamento 2013 e 2015 (vedi sotto per la risposta originale del 2011) :
Questo è cambiato a partire dalla specifica ES2015 (aka "ES6"): JavaScript ora ha dei proxy . I proxy ti consentono di creare oggetti che sono veri proxy per (facciate su) altri oggetti. Ecco un semplice esempio che trasforma i valori delle proprietà che sono stringhe in tutti i limiti al momento del recupero:
"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"
Le operazioni che non vengono ignorate hanno il comportamento predefinito. In quanto sopra, tutto ciò che sovrascrive è get
, ma c'è un intero elenco di operazioni a cui puoi agganciare.
Nell'elenco degli get
argomenti della funzione gestore:
target
è l'oggetto sottoposto a proxy ( original
, nel nostro caso).
name
è (ovviamente) il nome della proprietà da recuperare, che di solito è una stringa ma potrebbe anche essere un simbolo.
receiver
è l'oggetto che dovrebbe essere usato come this
nella funzione getter se la proprietà è un accessor anziché una proprietà data. Nel caso normale questo è il proxy o qualcosa che eredita da esso, ma può essere qualsiasi cosa poiché la trap può essere attivata da Reflect.get
.
Ciò ti consente di creare un oggetto con la funzione getter e setter che desideri:
"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}`);
L'output di quanto sopra è:
Ottenere 'foo' proprietà inesistenti
[before] obj.foo = non definito
Impostazione della proprietà inesistente 'pippo', valore iniziale: bar
[after] obj.foo = bar
Nota come otteniamo il messaggio "inesistente" quando proviamo a recuperare foo
quando non esiste ancora, e ancora quando lo creiamo, ma non dopo.
Risposta dal 2011 (vedi sopra per gli aggiornamenti 2013 e 2015) :
No, JavaScript non ha una funzione di proprietà generale. La sintassi del programma di accesso che stai utilizzando è descritta nella Sezione 11.1.5 delle specifiche e non offre caratteri jolly o simili.
Ovviamente potresti implementare una funzione per farlo, ma suppongo che probabilmente non vuoi usare f = obj.prop("foo");
piuttosto che f = obj.foo;
e obj.prop("foo", value);
piuttosto che obj.foo = value;
(che sarebbe necessario per la funzione per gestire proprietà sconosciute).
FWIW, la funzione getter (non mi sono preoccupato della logica setter) sarebbe simile a questa:
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...
};
Ma ancora una volta, non riesco a immaginare che vorresti davvero farlo, a causa di come cambia il modo in cui usi l'oggetto.