Metaprogrammierung bedeutet, dass Entwickler „die Sprache selbst programmieren“. Im Allgemeinen stellt die Programmiersprache einige APIs bereit, damit Entwickler bestimmte Funktionen der Sprache selbst bedienen können.
Ab ES6 wurden die Proxy- und Reflect-Funktionen hinzugefügt, die die Meta-Programmierfunktionen (Meta-Programmierung) erweitern und das Abfangen und Anpassen grundlegender Sprachoperationsverhaltensweisen (z. B. Attributsuche, Zuweisung, Aufzählung, Funktionsaufruf usw.).
Proxy (Proxy)
Proxy ist eine neue Funktion, die in ES6 hinzugefügt wurde. Es kann das native Verhalten des Objekts „proxy“ und ersetzen es mit benutzerdefiniertem Verhalten ausführen.
Proxy kann so verstanden werden, dass vor dem Zielobjekt eine „Abfangschicht“ eingerichtet wird. Der externe Zugriff auf das Objekt muss zunächst diese Abfangschicht durchlaufen, sodass ein Mechanismus, der externen Zugriff filtern und umschreiben kann. Die ursprüngliche Bedeutung des Wortes „Proxy“ bedeutet hier, dass es „im Auftrag“ bestimmter Vorgänge handelt. Es kann mit „Agent“ übersetzt werden.
Proxy-Objekte werden verwendet, um benutzerdefinierte Verhaltensweisen für grundlegende Vorgänge zu definieren (z. B. Eigenschaftssuche, Zuweisung, Aufzählung, Methodenaufruf usw.).
Erstellen Sie ein Proxy-Objekt:
Ziel: Ziel Das Objekt kann ein beliebiger Objekttyp sein, beispielsweise ein Array, eine Funktion oder sogar ein anderes Proxy-Objekt.
handlert: Handler-Objekt, das eine Reihe von Proxy-Methoden enthält, um verschiedene Verhaltensweisen des generierten Proxy-Objekts zu steuern.
Proxy-Objektmethoden:
Proxy.revocable(target, handler): wird zum Erstellen eines widerrufbaren Proxy-Objekts verwendet.
Das Prozessorobjekt verfügt über insgesamt 14 Proxy-Methoden:
handler.getPrototypeOf(): wird beim Lesen des Prototyps des Proxy-Objekts ausgelöst Dieser Vorgang, z. B. beim Ausführen von Object.getPrototypeOf(proxy).
handler.setPrototypeOf(): Dieser Vorgang wird beim Festlegen des Prototyps des Proxy-Objekts ausgelöst, beispielsweise beim Ausführen von Object.setPrototypeOf(proxy, null).
handler.isExtensible(): Dieser Vorgang wird ausgelöst, wenn ermittelt wird, ob ein Proxy-Objekt erweiterbar ist, beispielsweise beim Ausführen von Object.isExtensible(proxy).
handler.preventExtensions(): Wird ausgelöst, wenn ein Proxy-Objekt nicht erweiterbar gemacht wird, z. B. beim Ausführen von Object.preventExtensions(proxy).
handler.getOwnPropertyDescriptor(): Dieser Vorgang wird ausgelöst, wenn die Eigenschaftsbeschreibung einer Eigenschaft des Proxy-Objekts abgerufen wird, beispielsweise wenn Object.getOwnPropertyDescriptor(proxy, „foo“) ausgeführt wird.
handler.defineProperty(): Dieser Vorgang wird ausgelöst, wenn die Eigenschaftsbeschreibung einer Eigenschaft des Proxy-Objekts definiert wird, beispielsweise wenn Object.defineProperty(proxy, „foo“, { }) Stunde.
handler.has(): Dieser Vorgang wird ausgelöst, wenn festgestellt wird, ob das Proxy-Objekt ein bestimmtes Attribut hat, beispielsweise wenn „foo“ im Proxy ausgeführt wird.
handler.get(): Dieser Vorgang wird beim Lesen einer bestimmten Eigenschaft des Proxy-Objekts ausgelöst, beispielsweise beim Ausführen von Proxy.foo.
handler.set(): Dieser Vorgang wird ausgelöst, wenn einer Eigenschaft des Proxy-Objekts ein Wert zugewiesen wird, beispielsweise wenn Proxy.foo = 1 ausgeführt wird.
handler.deleteProperty(): Dieser Vorgang wird ausgelöst, wenn eine Eigenschaft des Proxy-Objekts gelöscht wird, beispielsweise wenn delete Proxy.foo ausgeführt wird.
handler.enumerate(): Dieser Vorgang wird beim Durchlaufen der Eigenschaften des Proxy-Objekts ausgelöst, beispielsweise beim Ausführen von for(i in Proxy){}.
handler.ownKeys(): Dieser Vorgang wird ausgelöst, wenn alle Eigenschaftsschlüssel des Proxy-Objekts abgerufen werden, beispielsweise beim Ausführen von Object.getOwnPropertyNames(proxy).
handler.apply(): Dieser Vorgang wird ausgelöst, wenn ein Proxy-Objekt aufgerufen wird, dessen Zielobjekt eine Funktion ist, beispielsweise beim Ausführen von Proxy().
handler.construct(): Dieser Vorgang wird beim Erstellen einer Instanz eines Proxy-Objekts ausgelöst, dessen Zielobjekt der Konstruktor ist, beispielsweise beim Ausführen von new Proxy().
Abfangen des Lesevorgangs des Attributwerts:
Im obigen Code Proxy (Das Proxy-)Objekt definiert ein Ziel und ein Handle, und das Handle implementiert eine Get-Capture-Methode. Durch diese Methode gibt das Proxy-Objekt für undefinierte Eigenschaften nicht mehr undefiniert zurück, sondern eine Zahl von 42.
Abfangen der Zuweisungsoperation des Attributwerts:
Oben Im Code wird die Set-Handler-Funktion festgelegt. Wenn das Attribut des Objekts, das wir abhören, geändert wird, können wir gleichzeitig anhand der Parameter erkennen, welches Attribut geändert wurde Wert, auf den es geändert wurde.
Die gleiche Abfangfunktion kann so eingestellt werden, dass sie mehrere Vorgänge abfängt:
Die Proxy.revocable-Methode wird verwendet, um ein widerrufbares Proxy-Objekt zu erstellen. Sobald ein Proxy-Objekt widerrufen wird, wird es fast vollständig nicht mehr verfügbar sein.
Reflect (Reflexion)
Eingeführt in ES6 Reflect ist eine weitere Metaprogrammierungsfunktion, die es uns ermöglicht, das native Verhalten von Objekten direkt zu manipulieren. Es besteht eine Eins-zu-eins-Entsprechung zwischen den steuerbaren Verhaltensweisen von Reflect und den Proxys von Proxy, wodurch es einfach ist, Reflect zum Aufrufen nativer Verhaltensweisen in den benutzerdefinierten Methoden von Proxy zu verwenden.
Reflection ist eine wertvolle Sprachfunktion, die die Metaprogrammierung fördert. Sie kann die Eigenschaften des Programms selbst dynamisch anzeigen, während das Programm ausgeführt wird.
Reflect-Objekt bietet 14 statische Methoden, deren Namen zufällig mit den Namen der 14 Proxy-Prozessormethoden identisch sind. Einige dieser 14 Methoden befinden sich zufällig auf den Objektobjektmethoden von Es gibt auch Geräte mit demselben Namen, und obwohl sie ähnlich funktionieren, gibt es feine Unterschiede.
Reflect.apply(): Rufen Sie eine Funktion auf und übergeben Sie ein Array als aufrufenden Parameter. Ähnlich wie Function.prototype.apply().
Reflect.construct(): Führt eine neue Operation am Konstruktor aus, was der Ausführung von new target(...args) entspricht.
Reflect.defineProperty(): Ähnlich wie Object.defineProperty().
Reflect.deleteProperty(): Das Löschen einer Eigenschaft des Objekts entspricht dem Ausführen von delete target[name].
Reflect.enumerate(): Diese Methode gibt einen Iterator zurück, der alle aufzählbaren eigenen String-Eigenschaften und geerbten String-Eigenschaften des Zielobjekts enthält, für...in Betrieb Es sind diese Eigenschaften, die werden durchquert.
Reflect.get(): Ruft den Wert eines Attributs für das Objekt ab, ähnlich wie bei target[name].
Reflect.getOwnPropertyDescriptor(): Ähnlich wie Object.getOwnPropertyDescriptor().
Reflect.getPrototypeOf(): Ähnlich wie Object.getPrototypeOf().
Reflect.has(): Bestimmt, ob ein Objekt ein bestimmtes Attribut hat. Es hat die gleiche Funktion wie der in-Operator.
Reflect.isExtensible(): Ähnlich wie Object.isExtensible().
Reflect.ownKeys(): Gibt ein Array zurück, das alle seine eigenen Eigenschaften enthält (mit Ausnahme geerbter Eigenschaften).
Reflect.preventExtensions(): Ähnlich wie Object.preventExtensions().
Reflect.set(): Legt den Wert eines Attributs für das Objekt fest, ähnlich wie bei target[name] = val.
Reflect.setPrototypeOf(): Ähnlich wie Object.setPrototypeOf().
Im obigen Code fängt die Proxy-Methode das Attributzuweisungsverhalten des Zielobjekts ab und verwendet das Reflect.set-Methode auf Der der Objekteigenschaft zugewiesene Wert.
Warum Reflect verwenden:
Fügen Sie einige Methoden des Object-Objekts ein, die offensichtlich in der Sprache enthalten sind (z. B. Object.defineProperty). Denken Sie über das Objekt nach. Zu diesem Zeitpunkt werden einige Methoden sowohl für Object- als auch für Reflect-Objekte bereitgestellt, und neue Methoden werden in Zukunft nur für Reflect-Objekte bereitgestellt.
Ändern Sie die Rückgabeergebnisse einiger Objektmethoden, um sie sinnvoller zu gestalten. Beispielsweise gibt Object.defineProperty(obj, name, desc) einen Fehler aus, wenn die Eigenschaft nicht definiert werden kann, während Reflect.defineProperty(obj, name, desc) false zurückgibt.
Lassen Sie Objektoperationen zu funktionalen Verhaltensweisen werden. Einige Objektoperationen sind zwingend erforderlich, z. B. „Name in obj“ und „lösche obj[Name]“, während Reflect.has(obj, name) und Reflect.deleteProperty(obj, name) sie in funktionale Verhaltensweisen umwandeln.
Die Methoden des Reflect-Objekts entsprechen eins zu eins den Methoden des Proxy-Objekts. Solange es sich um eine Methode des Proxy-Objekts handelt, kann die entsprechende Methode gefunden werden auf dem Reflect-Objekt. Dadurch kann das Proxy-Objekt problemlos die entsprechende Reflect-Methode aufrufen, um das Standardverhalten zu vervollständigen und als Grundlage für die Änderung des Verhaltens zu dienen. Mit anderen Worten: Unabhängig davon, wie Proxy das Standardverhalten ändert, können Sie bei Reflect immer das Standardverhalten erhalten.
Im obigen Code ruft jede Abfangoperation (Abrufen, Löschen, Has) des Proxy-Objekts intern die entsprechende Reflect-Methode auf. um sicherzustellen, dass das native Verhalten normal ausgeführt werden kann. Die zusätzliche Arbeit besteht darin, für jeden Vorgang eine Protokollzeile auszugeben. Mit dem Reflect-Objekt sind viele Vorgänge einfacher zu lesen.
Das obige ist der detaillierte Inhalt vonWeChat-Applet für die Entwicklung neuer ES6-Funktionen (6). Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!