Update 2013 und 2015 (siehe unten für die ursprüngliche Antwort von 2011) :
Dies wurde ab der ES2015-Spezifikation (auch bekannt als "ES6") geändert: JavaScript verfügt jetzt über Proxys . Mit Proxies können Sie Objekte erstellen, die echte Proxys für (Fassaden auf) anderen Objekten sind. Hier ist ein einfaches Beispiel, das alle Eigenschaftswerte, die Zeichenfolgen sind, beim Abrufen in alle Obergrenzen umwandelt:
"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"
Vorgänge, die Sie nicht überschreiben, haben ihr Standardverhalten. Oben überschreiben wir nur get
, aber es gibt eine ganze Liste von Operationen, an die Sie sich anschließen können.
In der get
Argumentliste der Handlerfunktion:
target
ist das Objekt, das vertreten wird ( original
in unserem Fall).
name
ist (natürlich) der Name der Eigenschaft, die abgerufen wird. Dies ist normalerweise eine Zeichenfolge, kann aber auch ein Symbol sein.
receiver
ist das Objekt, das wie this
in der Getter-Funktion verwendet werden soll, wenn die Eigenschaft eher ein Accessor als eine Dateneigenschaft ist. Im Normalfall ist dies der Proxy oder etwas, das von ihm erbt, aber es kann alles sein, da die Falle durch ausgelöst werden kann Reflect.get
.
Auf diese Weise können Sie ein Objekt mit der gewünschten Catch-All-Getter- und Setter-Funktion erstellen:
"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}`);
Die Ausgabe der oben genannten ist:
Nicht existierendes Eigentum 'foo' bekommen
[vor] obj.foo = undefiniert
Festlegen der nicht vorhandenen Eigenschaft 'foo', Anfangswert: bar
[nach] obj.foo = bar
Beachten Sie, wie wir die Nachricht "nicht vorhanden" erhalten, wenn wir versuchen, sie abzurufen, foo
wenn sie noch nicht vorhanden ist, und erneut, wenn wir sie erstellen, jedoch nicht danach.
Antwort von 2011 (siehe oben für Updates 2013 und 2015) :
Nein, JavaScript verfügt nicht über eine Catch-All-Eigenschaftsfunktion. Die von Ihnen verwendete Accessor-Syntax wird in Abschnitt 11.1.5 der Spezifikation behandelt und bietet keinen Platzhalter oder ähnliches.
Sie könnten natürlich eine Funktion implementieren, um dies zu tun, aber ich vermute, Sie möchten wahrscheinlich nicht f = obj.prop("foo");
eher als f = obj.foo;
und obj.prop("foo", value);
statt verwenden obj.foo = value;
(was notwendig wäre, damit die Funktion unbekannte Eigenschaften verarbeitet).
FWIW, die Getter-Funktion (ich habe mich nicht mit der Setter-Logik beschäftigt) würde ungefähr so aussehen:
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...
};
Aber ich kann mir auch nicht vorstellen, dass Sie das wirklich wollen, weil es die Art und Weise ändert, wie Sie das Objekt verwenden.