Get to know MDN better
Dieser Inhalt wurde automatisch aus dem Englischen übersetzt, und kann Fehler enthalten. Erfahre mehr über dieses Experiment.
Diese Funktion ist gut etabliert und funktioniert auf vielen Geräten und in vielen Browserversionen. Sie ist seit September 2016 browserübergreifend verfügbar.
Das Proxy-Objekt ermöglicht Ihnen, einen Proxy für ein anderes Objekt zu erstellen, der die grundlegenden Operationen für dieses Objekt abfangen und neu definieren kann.
Das Proxy-Objekt ermöglicht Ihnen, ein Objekt zu erstellen, das anstelle des Originalobjekts verwendet werden kann, aber grundlegende Object-Operationen wie das Lesen, Setzen und Definieren von Eigenschaften neu definieren kann. Proxy-Objekte werden häufig verwendet, um den Zugriff auf Eigenschaften zu protokollieren, Eingaben zu validieren, zu formatieren oder zu bereinigen und vieles mehr.
Sie erstellen einen Proxy mit zwei Parametern:
Zum Beispiel erstellt dieser Code einen Proxy für das target-Objekt.
Da der Handler leer ist, verhält sich dieser Proxy genauso wie das ursprüngliche Ziel:
Um den Proxy anzupassen, definieren wir Funktionen im Handler-Objekt:
Hier haben wir eine Implementierung des get() Handlers bereitgestellt, der Zugriffsversuche auf Eigenschaften im Ziel abfängt.
Handler-Funktionen werden manchmal als Traps bezeichnet, vermutlich weil sie Aufrufe an das Zielobjekt abfangen. Der Trap im obigen handler2 definiert alle Eigenschafts-Accessoren neu:
Proxys werden oft mit dem Reflect-Objekt verwendet, das einige Methoden mit denselben Namen wie die Proxy-Traps bereitstellt. Die Reflect-Methoden bieten die reflexiven Semantiken für das Aufrufen der entsprechenden objektinternen Methoden. Zum Beispiel können wir Reflect.get aufrufen, wenn wir das Verhalten des Objekts nicht neu definieren möchten:
Die Reflect-Methode interagiert immer noch mit dem Objekt durch objektinterne Methoden — sie „deproxifiziert“ den Proxy nicht, wenn sie auf einem Proxy aufgerufen wird. Wenn Sie Reflect-Methoden innerhalb eines Proxy-Traps verwenden und der Reflect-Methodenaufruf erneut vom Trap abgefangen wird, kann es zu einer Endlosschleife kommen.
Die folgenden Begriffe werden verwendet, wenn über die Funktionalität von Proxys gesprochen wird.
handlerDas Objekt, das als zweites Argument an den Proxy-Konstruktor übergeben wird. Es enthält die Traps, die das Verhalten des Proxys definieren.
trapDie Funktion, die das Verhalten für die entsprechende objektinterne Methode definiert. (Dies ist analog zum Konzept der Traps in Betriebssystemen.)
targetObjekt, das der Proxy virtualisiert. Es wird oft als Speicher-Backend für den Proxy verwendet. Invarianten (Semantiken, die unverändert bleiben) in Bezug auf die Nichterweiterbarkeit des Objekts oder nicht konfigurierbare Eigenschaften werden gegen das Ziel überprüft.
invariantsSemantiken, die unverändert bleiben, wenn benutzerdefinierte Operationen implementiert werden. Wenn Ihre Trap-Implementierung die Invarianten eines Handlers verletzt, wird ein TypeError ausgelöst.
Objekte sind Sammlungen von Eigenschaften. Die Sprache bietet jedoch keine Mechanismen, um die im Objekt gespeicherten Daten direkt zu manipulieren — stattdessen definiert das Objekt einige interne Methoden, die spezifizieren, wie mit ihm interagiert werden kann. Zum Beispiel, wenn Sie obj.x lesen, erwarten Sie vielleicht, dass Folgendes passiert:
Es gibt nichts Besonderes an diesem Prozess in der Sprache — es liegt daran, dass gewöhnliche Objekte standardmäßig eine [[Get]]-interne Methode haben, die mit diesem Verhalten definiert ist. Die obj.x-Eigenschaftsabzugssyntax ruft einfach die [[Get]]-Methode des Objekts auf und das Objekt verwendet seine eigene interne Methodenumsetzung, um zu bestimmen, was zurückgegeben werden soll.
Ein anderes Beispiel: Arrays unterscheiden sich von normalen Objekten, da sie eine magische length-Eigenschaft haben, die, wenn modifiziert, automatisch leere Slots zuordnet oder Elemente aus dem Array entfernt. Ebenso ändert das Hinzufügen von Array-Elementen automatisch die length-Eigenschaft. Dies liegt daran, dass Arrays eine [[DefineOwnProperty]]-interne Methode haben, die weiß, length zu aktualisieren, wenn ein ganzzahliger Index geschrieben wird, oder die Array-Inhalte zu aktualisieren, wenn length geschrieben wird. Solche Objekte, deren interne Methoden unterschiedliche Implementierungen als gewöhnliche Objekte haben, werden als exotische Objekte bezeichnet. Proxy ermöglicht es Entwicklern, ihre eigenen exotischen Objekte mit voller Kapazität zu definieren.
Alle Objekte haben die folgenden internen Methoden:
| [[GetPrototypeOf]] | getPrototypeOf() |
| [[SetPrototypeOf]] | setPrototypeOf() |
| [[IsExtensible]] | isExtensible() |
| [[PreventExtensions]] | preventExtensions() |
| [[GetOwnProperty]] | getOwnPropertyDescriptor() |
| [[DefineOwnProperty]] | defineProperty() |
| [[HasProperty]] | has() |
| [[Get]] | get() |
| [[Set]] | set() |
| [[Delete]] | deleteProperty() |
| [[OwnPropertyKeys]] | ownKeys() |
Funktionsobjekte haben auch die folgenden internen Methoden:
| [[Call]] | apply() |
| [[Construct]] | construct() |
Es ist wichtig zu erkennen, dass alle Interaktionen mit einem Objekt letztendlich auf die Aufrufung einer dieser internen Methoden hinauslaufen und dass sie alle durch Proxys anpassbar sind. Das bedeutet, dass fast kein Verhalten (außer bestimmte kritische Invarianten) in der Sprache garantiert ist — alles wird durch das Objekt selbst definiert. Wenn Sie delete obj.x ausführen, gibt es keine Garantie dafür, dass "x" in obj danach false zurückgibt — es hängt von den Implementierungen des Objekts von [[Delete]] und [[HasProperty]] ab. Ein delete obj.x kann Dinge in die Konsole protokollieren, einen globalen Status ändern oder sogar eine neue Eigenschaft definieren, anstatt die bestehende zu löschen, obwohl diese Semantiken in Ihrem eigenen Code vermieden werden sollten.
Alle internen Methoden werden von der Sprache selbst aufgerufen und sind in JavaScript-Code nicht direkt zugänglich. Der Reflect-Namensraum bietet Methoden, die wenig mehr tun, als die internen Methoden aufzurufen, außer einigen Eingabenormalisierungen und -validierungen. Auf jeder Trap-Seite listen wir mehrere typische Situationen auf, wann der Trap aufgerufen wird, aber diese internen Methoden werden an sehr vielen Stellen aufgerufen. Zum Beispiel lesen und schreiben Array-Methoden auf Array durch diese internen Methoden, sodass Methoden wie push() auch get()- und set()-Traps aufrufen würden.
Die meisten internen Methoden sind in ihrem Zweck klar. Die einzigen beiden, die verwirrt werden könnten, sind [[Set]] und [[DefineOwnProperty]]. Für normale Objekte ruft erstere Setter auf; letztere nicht. (Und [[Set]] ruft [[DefineOwnProperty]] intern auf, wenn keine bestehende Eigenschaft vorhanden ist oder die Eigenschaft eine Dateneigenschaft ist.) Während Sie vielleicht wissen, dass die obj.x = 1-Syntax [[Set]] verwendet und Object.defineProperty() [[DefineOwnProperty]] verwendet, ist es nicht sofort ersichtlich, welche Semantiken andere eingebaute Methoden und Syntaxen verwenden. Zum Beispiel verwenden Klassenfelder die [[DefineOwnProperty]]-Semantik, weshalb Setter, die in der Superklasse definiert sind, nicht aufgerufen werden, wenn ein Feld in der abgeleiteten Klasse deklariert wird.
Erstellt ein neues Proxy-Objekt.
Hinweis: Es gibt keine Proxy.prototype-Eigenschaft, daher haben Proxy-Instanzen keine speziellen Eigenschaften oder Methoden.
Erstellt ein widerrufbares Proxy-Objekt.
In diesem Beispiel wird die Zahl 37 als Standardwert zurückgegeben, wenn der Eigenschaftsname nicht im Objekt vorhanden ist. Es wird der get() Handler verwendet.
In diesem Beispiel verwenden wir ein natives JavaScript-Objekt, an das unser Proxy alle Operationen weiterleiten wird, die darauf angewendet werden.
Beachten Sie, dass dieses "No-op" für einfache JavaScript-Objekte funktioniert, aber nicht für native Objekte wie DOM-Elemente, Map-Objekte oder alles, was interne Slots hat. Siehe keine Weiterleitung privater Felder für weitere Informationen.
Ein Proxy ist weiterhin ein anderes Objekt mit einer anderen Identität — er ist ein Proxy, der zwischen dem umhüllten Objekt und der Außenwelt operiert. Daher hat der Proxy keinen direkten Zugriff auf die privaten Elemente des Originalobjekts.
Dies liegt daran, dass, wenn der get-Trap des Proxys aufgerufen wird, this-Wert der proxy anstelle des ursprünglichen secret ist, sodass #secret nicht zugänglich ist. Um dies zu beheben, verwenden Sie das ursprüngliche secret als this:
Für Methoden bedeutet dies, dass Sie den this-Wert der Methode auf das ursprüngliche Objekt ebenfalls umleiten müssen:
Einige native JavaScript-Objekte haben Eigenschaften, die als interne Slots bezeichnet werden und die vom JavaScript-Code nicht zugänglich sind. Zum Beispiel haben Map-Objekte einen internen Slot namens [[MapData]], der die Schlüssel-Wert-Paare der Karte speichert. Daher können Sie nicht trivial einen Weiterleitungsproxy für eine Karte erstellen:
Sie müssen den oben illustrierten „this-Wiederherstellungs“-Proxy verwenden, um dies zu umgehen.
Mit einem Proxy können Sie leicht den übergebenen Wert für ein Objekt validieren. Dieses Beispiel verwendet den set() Handler.
In diesem Beispiel verwenden wir Proxy, um ein Attribut von zwei verschiedenen Elementen umzuschalten: Wenn wir das Attribut an einem Element setzen, wird das Attribut am anderen automatisch gelöscht.
Wir erstellen ein view-Objekt, das ein Proxy für ein Objekt mit einer selected-Eigenschaft ist. Der Proxy-Handler definiert den set() Handler.
Wenn wir ein HTML-Element view.selected zuweisen, wird das 'aria-selected'-Attribut des Elements auf true gesetzt. Wenn wir dann ein anderes Element view.selected zuweisen, wird das 'aria-selected'-Attribut dieses Elements auf true gesetzt und das vorherige Element's 'aria-selected'-Attribut wird automatisch auf false gesetzt.
Das products-Proxy-Objekt bewertet den übergebenen Wert und konvertiert ihn bei Bedarf in ein Array. Das Objekt unterstützt auch eine zusätzliche Eigenschaft namens latestBrowser sowohl als Getter als auch als Setter.
| ECMAScript® 2027 Language Specification # sec-proxy-objects |
JavaScript aktivieren, um diese Browser-Kompatibilitätstabelle anzuzeigen.
Der Bauplan für ein besseres Internet.
Besuche die gemeinnützige Muttergesellschaft der Mozilla Corporation, die Mozilla Foundation.
Teile dieses Inhalts sind ©1998–2026 von einzelnen mozilla.org-Mitwirkenden. Inhalte sind verfügbar unter einer Creative-Commons-Lizenz.