Wie erhalte ich das Ziel eines JavaScript-Proxys?

Lesezeit: 6 Minuten

Adams Benutzeravatar
Adam

So greifen Sie auf das Ziel zu (das ist myArray) von myProxy Hier?

function createProxy() {
  const myArray = [Math.random(), Math.random()];
  return new Proxy(myArray, {});
}

const myProxy = createProxy();

Ich hätte gerne eine getProxyTarget Funktion, die das ursprüngliche Objekt zurückgeben würde, ohne einen anderen Teil des Codes zu ändern:

let original;
function createProxy() {
  const myArray = [Math.random(), Math.random()];
  original = myArray;
  return new Proxy(myArray, {});
}

const myProxy = createProxy();

function getProxyTarget(proxy){ /* ... your code */ }

console.log(getProxyTarget(myProxy) === original) // should be true

  • Das kannst du nicht. Deshalb ist es ein Proxy. Was versuchst du zu tun, warum brauchst du das?

    – Bergi

    29. Juni 2018 um 7:54

  • @Bergi Denn wenn ich ein Objekt mit Zirkelverweisen habe und diese Zirkelverweise sich in Proxys befinden, gibt es keine Möglichkeit dazu sicher stringifizieren mein Objekt. Ich erhalte die Fehlermeldung „Stapelgröße überschritten“. 🙁

    – Adam

    29. Juni 2018 um 7:59


  • Können Sie bitte ein Beispiel dafür geben? Zirkelverweise (ich glaube, Sie meinen diese, nicht Abhängigkeiten) sollte problemlos mit Proxys funktionieren, z myProxy === myProxy hält immer noch. Nichts muss das Ziel erreichen.

    – Bergi

    29. Juni 2018 um 8:02 Uhr

Caleb Waldners Benutzeravatar
Caleb Waldner

Wenn Sie Vue 3 verwenden und mit Proxies arbeiten, bietet Vue einige Methoden, die Ihnen dabei helfen:

import { isProxy, toRaw } from 'vue';

Mithilfe dieser können Sie überprüfen, ob ein Objekt ein Proxy ist isProxyZum Beispiel:

isProxy(reactiveObjectOrArray) ? 'yup' : 'nope'

Und Sie können die Rohdaten mit extrahieren toRaw:

const rawObjectOrArray = toRaw(reactiveObjectOrArray)

Weitere Informationen zu toRaw Und isProxy

  • Seltsamerweise, isProxy Und toRaw Scheint nur mit reaktiven Objekten zu funktionieren, die mit erstellt wurden reactive Funktion, nicht die häufigere ref. Wie um alles in der Welt soll man das Originalobjekt für einen bekommen? ref reaktiver Wert?

    – Jez

    7. November 2022 um 12:04

  • Interessanterweise musste ich nie einen konvertieren ref Das ist mir also nie aufgefallen, aber wenn ich es selbst teste, sehe ich, dass Sie Recht haben; A ref funktioniert mit diesen beiden Funktionen nicht. Wenn jemand wirklich einen konvertieren müsste refsie könnten es gebrauchen toReactive von VueUse, wodurch ich meine konvertieren konnte ref in ein reaktives Objekt. Das hat bei mir funktioniert, aber ich glaube, es funktioniert nur bei Objekten; Zeichenfolgen, boolesche Werte und dergleichen funktionieren mit dieser Methode möglicherweise nicht.

    – Caleb Waldner

    8. November 2022 um 4:27

  • Haben Sie das mit einer Vorlagenreferenz versucht, bei der ich den zugrunde liegenden Typ herausfinden wollte? const playfieldRef = ref(null); const pref = playfieldRef; const prefValue = playfieldRef.value; const prefReactive = toReactive(pref); const prIsProxy = isProxy(prefReactive); /* false */ const prRaw = toRaw(prefReactive); /* Proxy {} */

    – Jez

    8. November 2022 um 11:44 Uhr

  • Versuchen const prefReactive = toReactive(pref.value);. Funktioniert es?

    – Caleb Waldner

    9. November 2022 um 2:48

  • Ja, das habe ich auch ausprobiert, es ist seltsam, es gibt mir einen etwas anderen Proxy zurück, der mir bei der Auswertung Folgendes in der Konsole anzeigt: Proxy {__v_skip: true, getStage: ƒ, getNode: ƒ}. Wenn ich das Objekt öffne, hat es [[Handler]]: Object, [[Target]]: ProxyUnd [[IsRevoked]]: false drauf, aber nicht getStage oder getNode Funktionen. Scheint immer noch kein zugrunde liegendes Objekt zu sein; es sei denn, ich bin dumm und die Originalbibliothek stellt tatsächlich selbst einen Proxy bereit. Hmm.

    – Jez

    10. November 2022 um 11:01 Uhr


Benutzeravatar von Rashad Saleh
Rashad Saleh

Mit können Sie eine Kopie der vom Proxy zurückgegebenen Daten erstellen Object.assign():

const target_copy = Object.assign({}, my_proxy);

Das wird für alle funktionieren aufzählbare eigene Eigenschaften auf dem Proxy/Ziel vorhanden.

  • Mein Beispielszenario erforderte die Verarbeitung eines Proxys, der als Promise-Ablehnung von einem Web-API-Aufruf zurückgegeben wurde. Die vollständige Zeile sah so aus: var m = Object.assign({}, rejected)[0].message; . Danke Rashad!

    – Shanerk

    23. Januar 2019 um 19:54

  • Dies beantwortet die Frage nicht. Die Daten von target_copy wird weiterhin von Proxy-Accessoren beeinflusst; und Sie haben keinen Verweis auf das Originalobjekt.

    – Leonardo Raele

    4. Oktober 2021 um 6:12 Uhr

  • Dies funktioniert nicht, wenn das Ziel ein Array ist und Sie das Array zurückerhalten möchten.

    – Chetan

    17. November 2021 um 7:30 Uhr

Ich finde, dass ich (bei Verwendung von Vue.js, wo manchmal Proxy-Objekte beteiligt sind, z. B. beim Beobachten einer Komponenten-Requisite) das Ziel sowohl erhalten kann, wenn es ein Objekt ist, als auch wenn es ein Array ist JSON.stringify:

let myTarget = JSON.parse(JSON.stringify(myProxy))

Dieser Ansatz funktioniert auch mit Array-Zielen Object.assign({}, myProxy) Funktioniert nur, wenn das Ziel ein Objekt ist.

Aber ich bin ein Neuling in Sachen JavaScript-Proxys und meine Kenntnisse sind begrenzt. Möglicherweise verstehe ich die Einschränkungen und Vorbehalte dieses Ansatzes nicht. Trotzdem hilft es vielleicht jemandem!

  • Danke. Das ist es, was ich brauchte. Ich brauchte das Ziel eines von Vue erstellten Proxys, damit ich es als Teil einer Abrufanforderung übergeben konnte.

    – Mike Ryan

    23. Januar 2021 um 22:24

  • Gute Antwort für ältere Versionen, aber ziehen Sie toRaw in Betracht, wenn Sie Vue3 verwenden …

    – JL Peyret

    1. November 2022 um 7:25 Uhr

Davidiusdadis Benutzeravatar
Davidiusdadi

Wie die anderen Antworten bereits sagten a Proxy erhält Falle kann eine elegante Lösung sein.

const IDENTITY = Symbol('proxy_target_identity')
const handler = {
  get: (target, property, receiver) => {
    if (property === IDENTITY) {
      return target
    }
    return Reflect.get(target, property, receiver)
  }
}
function createProxy() {
    const myArray = [Math.random(), Math.random()];
    return new Proxy(myArray, handler);
}
const myProxy = createProxy();
const orignal_target = myProxy[IDENTITY]

Dieses Codebeispiel sollte ziemlich robust sein, da es:

  • vermeidet Konflikte bei Eigenschaftsnamen durch die Verwendung von a Symbol
  • deckt alle Get-Szenarien mit ab Reflect.get anstatt target[property]
  • WARNUNG: Seien Sie vorsichtig bei der Prototypenvererbung – für den Fall, dass Ihr Proxy letztendlich als Prototyp verwendet wird not_itself_a_proxy[IDENTITY] Der Anruf wird nicht zurückgegeben not_itself_a_proxy sondern die „Identität“ des Prototyps!

Es gibt eine clevere Möglichkeit, dies zu tun: Sie können eine hinzufügen erhalten trap an den Proxy senden und ihn zurückgeben lassen Ziel bedingt. So..

let resolveMode = false;  // Switch that controls if getter returns target or prop. 

function resolve(obj) {
    resolveMode = true;  // Turn on our switch
    let target = obj.anything;  // This gets the target not the prop!
    resolveMode = false;  // Turn off the switch for the getter to behave normally
    return target;  // Return what we got!
}

function createProxy() {
    const myArray = [Math.random(), Math.random()];
    return new Proxy(myArray, {
        get: function(target, prop) {
            if (resolveMode) return target;  // This is where the magic happens!
            else return target[prop];        // This is normal behavior..
        }
    });
}

const myProxy = createProxy();
let target = resolve(myProxy);

Denken Sie daran, dass die Leistung des Objekts umso langsamer wird, je mehr Codezeilen Sie zu Traps hinzufügen. Hoffe das hilft.

  • Dies ist nur dann möglich, wenn Sie Zugriff auf den Quellcode des Proxys haben.

    – Leonardo Raele

    4. Okt. 2021 um 6:13

Timkays Benutzeravatar
Timkay

Die anderen Antworten gaben einige gute Lösungen. Hier ist die Antwort von @Yuci für Klassen zusammengefasst. In diesem Fall ist es so einfach wie das Definieren einer Instanzvariablen mit einem speziellen Namen. Die Proxy-Get-Funktion gibt es zurück, ebenso wie das zugrunde liegende Ziel.

class Foo {
    constructor() {
        this.__target__ = this;
        return new Proxy(this, {
            get: function (target, name) {
                if (name in target) return target[name];
                // your code here
            }
        });
    }
}

let foo = new Foo();
let target = foo.__target__;
console.log('proxied Foo', foo);
console.log('recovered target', target, target.__target__.__target__);

  • Dies ist nur dann möglich, wenn Sie Zugriff auf den Quellcode des Proxys haben.

    – Leonardo Raele

    4. Okt. 2021 um 6:13

Wie wäre es mit dem Hinzufügen der folgenden Get-Trap:

const handler = {
  get: (target, property, receiver) => {
    if (property === 'myTarget') {
      return target
    }
    return target[property]
  }
}

const myArray = [Math.random(), Math.random()];

function createProxy() {
//     const myArray = [Math.random(), Math.random()];
    return new Proxy(myArray, handler);
}

const myProxy = createProxy();

Und Sie können das Ziel des Proxys ermitteln myProxy.myTarget:

console.log(myProxy.myTarget) // [0.22089416118932403, 0.08429264462405173]
console.log(myArray === myProxy.myTarget) // true

1453910cookie-checkWie erhalte ich das Ziel eines JavaScript-Proxys?

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy