--- title: Meta programming slug: Web/JavaScript/Guide/Meta_programming tags: - Guide - JavaScript - Proxy - Reflect - 'l10n:priority' translation_of: Web/JavaScript/Guide/Meta_programming ---
Beginnend mit ECMAScript 2015 hat JavaScript Unterstützung für {{jsxref("Proxy")}} and {{jsxref("Reflect")}} Objekte erhalten, welche das Abfangen und Definieren von benutzerdefinierten Verhaltens für grundlegenden Sprachoperation erlaubt (z. B. Eigenschaftensuche, Zuweisung, Aufzählung, Funktionsaufruf usw.). Mit der Hilfe dieser beiden Objekte ist es möglich auf der Metaebene von JavaScript zu programmieren.
Eingeführt in ECMAScript 6 erlaubt das {{jsxref("Proxy")}} Objekt das Abfangen und Definieren von benutzerdefinierten Verhaltens für bestimmte Operationen. Zum Beispiel um die Eigenschaft eines Objektes zu erhalten:
var handler = {
get: function(target, name) {
return name in target ? target[name] : 42;
}
};
var p = new Proxy({}, handler);
p.a = 1;
console.log(p.a, p.b); // 1, 42
Das Proxy Objekt definiert einen Ziel (target) (hier ein leeres Objekt) und einen handler (Verhaltens) Objekt in dem ein get Trap implementiert ist. In diesem Beispiel wird kein undefined zurückgegeben, wenn Eigenschaften nicht definiert sind. Stattdessen wird die Zahl 42 zurückgegeben.
Weitere Beispiele sind auf der {{jsxref("Proxy")}} Referenzseite verfügbar.
Die folgenden Terme werden im Zusammenhang mit der Funktionalität von Proxies verwendet.
Die Folgende Tabelle fasst die verfügbaren Traps von Proxy Objekten zusammen. Siehe auf der Referenzseite für detailliertere Erklärungen und Beispiele.
| Handler / Trap | Interceptions | Invarianten |
|---|---|---|
| {{jsxref("Global_Objects/Proxy/handler/getPrototypeOf", "handler.getPrototypeOf()")}} | {{jsxref("Object.getPrototypeOf()")}} {{jsxref("Reflect.getPrototypeOf()")}} {{jsxref("Object/proto", "__proto__")}} {{jsxref("Object.prototype.isPrototypeOf()")}} {{jsxref("Operators/instanceof", "instanceof")}} |
|
| {{jsxref("Global_Objects/Proxy/handler/setPrototypeOf", "handler.setPrototypeOf()")}} | {{jsxref("Object.setPrototypeOf()")}} {{jsxref("Reflect.setPrototypeOf()")}} |
Wenn target nicht erweiterbar ist, muss der prototype Parameter der gleiche Wert sein wie Object.getPrototypeOf(target). |
| {{jsxref("Global_Objects/Proxy/handler/isExtensible", "handler.isExtensible()")}} | {{jsxref("Object.isExtensible()")}} {{jsxref("Reflect.isExtensible()")}} |
Object.isExtensible(proxy) muss den gleichen Wert wie Object.isExtensible(target) zurückgeben. |
| {{jsxref("Global_Objects/Proxy/handler/preventExtensions", "handler.preventExtensions()")}} | {{jsxref("Object.preventExtensions()")}} {{jsxref("Reflect.preventExtensions()")}} |
Object.preventExtensions(proxy) gibt nur true zurück, wenn Object.isExtensible(proxy) false ist. |
| {{jsxref("Global_Objects/Proxy/handler/getOwnPropertyDescriptor", "handler.getOwnPropertyDescriptor()")}} | {{jsxref("Object.getOwnPropertyDescriptor()")}} {{jsxref("Reflect.getOwnPropertyDescriptor()")}} |
|
| {{jsxref("Global_Objects/Proxy/handler/defineProperty", "handler.defineProperty()")}} | {{jsxref("Object.defineProperty()")}} {{jsxref("Reflect.defineProperty()")}} |
|
| {{jsxref("Global_Objects/Proxy/handler/has", "handler.has()")}} | Eigenschaftsabfrage: foo in proxyVererbte Eigenschaftsabfrage: foo in Object.create(proxy){{jsxref("Reflect.has()")}} |
|
| {{jsxref("Global_Objects/Proxy/handler/get", "handler.get()")}} | Eigenschaftszugriff: proxy[foo]and proxy.barVererbter Eigenschaftszugriff: Object.create(proxy)[foo]{{jsxref("Reflect.get()")}} |
|
| {{jsxref("Global_Objects/Proxy/handler/set", "handler.set()")}} | Eigenschaftszuweisung: proxy[foo] = bar and proxy.foo = barVererbte Eigenschaftszuweisung: Object.create(proxy)[foo] = bar{{jsxref("Reflect.set()")}} |
|
| {{jsxref("Global_Objects/Proxy/handler/deleteProperty", "handler.deleteProperty()")}} | Eigenschaft löschen: delete proxy[foo] und delete proxy.foo{{jsxref("Reflect.deleteProperty()")}} |
Eine Eigenschaft kann nicht gelöscht werden, Wenn sie als nicht konfigurierbare Eigenschaft im Zielobjekt existiert. |
| {{jsxref("Global_Objects/Proxy/handler/enumerate", "handler.enumerate()")}} | Eigenschaft aufzählen (enumeration) / for...in: for (var name in proxy) {...}{{jsxref("Reflect.enumerate()")}} |
Die enumerate Methode muss ein Objekt zurückgeben. |
| {{jsxref("Global_Objects/Proxy/handler/ownKeys", "handler.ownKeys()")}} | {{jsxref("Object.getOwnPropertyNames()")}} {{jsxref("Object.getOwnPropertySymbols()")}} {{jsxref("Object.keys()")}} {{jsxref("Reflect.ownKeys()")}} |
|
| {{jsxref("Global_Objects/Proxy/handler/apply", "handler.apply()")}} | proxy(..args){{jsxref("Function.prototype.apply()")}} and {{jsxref("Function.prototype.call()")}} {{jsxref("Reflect.apply()")}} |
Es gibt keine Invarianten für die handler.apply Methode. |
| {{jsxref("Global_Objects/Proxy/handler/construct", "handler.construct()")}} | new proxy(...args){{jsxref("Reflect.construct()")}} |
Das Ergebnis muss ein Object sein. |
ProxyDie {{jsxref("Proxy.revocable()")}} Methode wird benutzt, um ein widerrufbares Proxy Objekt zu erstellen. Das bedeutet, dass der Proxy mit der Funktion revoke widerrufen werden kann und der Proxy ausgeschaltet wird. Danach wird jede Operation auf dem Proxy zu einem {{jsxref("TypeError")}} führen.
var revocable = Proxy.revocable({}, {
get: function(target, name) {
return '[[' + name + ']]';
}
});
var proxy = revocable.proxy;
console.log(proxy.foo); // "[[foo]]"
revocable.revoke();
console.log(proxy.foo); // TypeError is thrown
proxy.foo = 1; // TypeError again
delete proxy.foo; // still TypeError
typeof proxy; // "object", typeof doesn't trigger any trap
{{jsxref("Reflect")}} ist ein Standardobjekt welches Methoden unterstützt, welche das Abfragen von JavaScript Operationen erlauben. Die Methoden sind die gleichen wie die eines {{jsxref("Global_Objects/Proxy/handler","Proxy Handlers","","true")}}. Reflect ist kein Funktionsobjekt.
Reflect hilft beim Weiterleiten von Standardoperationen des Handlers zu dem Zielobjekt.
Mit bekommt man {{jsxref("Reflect.has()")}} zum Beispiel den in Operator als Funktion:
Reflect.has(Object, 'assign'); // true
apply FunktionIn ES5 wird typischerweise die {{jsxref("Function.prototype.apply()")}} Methode genutzt, um eine Funktion mit einem gegebenen this Wert und arguments als Array (oder ein Array-ähnliches Objekt) benutzt.
Function.prototype.apply.call(Math.floor, undefined, [1.75]);
Mit {{jsxref("Reflect.apply")}} wird dieses weniger Langatmig und leichter verständlich:
Reflect.apply(Math.floor, undefined, [1.75]);
// 1;
Reflect.apply(String.fromCharCode, undefined, [104, 101, 108, 108, 111]);
// "hello"
Reflect.apply(RegExp.prototype.exec, /ab/, ['confabulation']).index;
// 4
Reflect.apply(''.charAt, 'ponies', [3]);
// "i"
Mit {{jsxref("Object.defineProperty")}}, welche ein Objekt zurück gibt, wenn es erfolgreich war, oder andernfalls ein {{jsxref("TypeError")}} erzeugt, muss man ein {{jsxref("Statements/try...catch","try...catch")}} Block benutzen, um einen Fehler bei der Definition einer Eigenschaft abzufangen. Weil {{jsxref("Reflect.defineProperty")}} einen Boolean als Status zurück gibt, kann man einfach einen {{jsxref("Statements/if...else","if...else")}} Block benutzen:
if (Reflect.defineProperty(target, property, attributes)) {
// success
} else {
// failure
}
{{Previous("Web/JavaScript/Guide/Iterators_and_Generators")}}