--- 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 proxy Vererbte Eigenschaftsabfrage: foo in Object.create(proxy) {{jsxref("Reflect.has()")}} |
|
{{jsxref("Global_Objects/Proxy/handler/get", "handler.get()")}} | Eigenschaftszugriff: proxy[foo] and proxy.bar Vererbter Eigenschaftszugriff: Object.create(proxy)[foo] {{jsxref("Reflect.get()")}} |
|
{{jsxref("Global_Objects/Proxy/handler/set", "handler.set()")}} | Eigenschaftszuweisung: proxy[foo] = bar and proxy.foo = bar Vererbte 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. |
Proxy
Die {{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")}}