Adán
Cómo acceder al destino (que es myArray
) de myProxy
¿aquí?
function createProxy() {
const myArray = [Math.random(), Math.random()];
return new Proxy(myArray, {});
}
const myProxy = createProxy();
Caleb Waldner
Si está utilizando Vue 3 y está tratando con Proxies, Vue proporciona algunos métodos para ayudar con esto:
import { isProxy, toRaw } from 'vue';
Usando estos, puede verificar si un objeto es un proxy con isProxy
por ejemplo:
isProxy(reactiveObjectOrArray) ? 'yup' : 'nope'
Y puede extraer los datos sin procesar usando toRaw
:
const rawObjectOrArray = toRaw(reactiveObjectOrArray)
-
Extrañamente,
isProxy
ytoRaw
solo parecen funcionar con objetos reactivos creados con elreactive
función, no la más comúnref
. ¿Cómo diablos pretende obtener el objeto original para unref
valor reactivo?– Jez
7 de noviembre de 2022 a las 12:04
-
Interesante, nunca necesité convertir un
ref
así que nunca me di cuenta de esto, pero al probarme a mí mismo, veo que tienes razón; aref
no funciona con esas dos funciones. Si alguien realmente necesitara convertir unref
podrían usartoReactive
de VueUse, que me permitió convertir miref
en un objeto reactivo. Esto funcionó para mí, pero creo que solo funciona para objetos; cadena, booleanos y similares podrían no funcionar con este método.–Caleb Waldner
8 de noviembre de 2022 a las 4:27
-
¿Intentó eso con una referencia de plantilla, que es lo que estaba tratando de descubrir el tipo subyacente?
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 de noviembre de 2022 a las 11:44
-
Intentar
const prefReactive = toReactive(pref.value);
. ¿Eso funciona?–Caleb Waldner
9 de noviembre de 2022 a las 2:48
-
Sí, también probé ese, es extraño, me devuelve un Proxy ligeramente diferente que me muestra esto en la consola cuando se evalúa:
Proxy {__v_skip: true, getStage: ƒ, getNode: ƒ}
. Cuando abro el objeto tiene[[Handler]]: Object
,[[Target]]: Proxy
y[[IsRevoked]]: false
en eso, pero nogetStage
ogetNode
funciones Todavía no parece un objeto subyacente; a menos que esté siendo tonto y la biblioteca original en realidad expone un Proxy en sí. Mmm.– Jez
10 de noviembre de 2022 a las 11:01
Rashad Saleh
Puede hacer una copia de los datos devueltos por el proxy usando Object.assign()
:
const target_copy = Object.assign({}, my_proxy);
Esto funcionará para todos propiedades propias enumerables existente en el proxy/objetivo.
-
Mi escenario de ejemplo requería manejar un proxy devuelto como un rechazo de promesa de una llamada a la API web. La línea completa se veía así:
var m = Object.assign({}, rejected)[0].message;
. Gracias Rashad!– Shane Kenyon
23 de enero de 2019 a las 19:54
-
Esto no responde la pregunta. los datos de
target_copy
aún se verá afectado por los accesores proxy; y no tendrá la referencia al objeto original.–Leonardo Raele
4 de octubre de 2021 a las 6:12
-
Esto no funciona si el objetivo es una matriz y desea recuperar la matriz.
– chetano
17 de noviembre de 2021 a las 7:30
Descubrí que (usando Vue.js donde a veces están involucrados objetos Proxy, por ejemplo, cuando veo un accesorio de componente) puedo obtener el objetivo tanto si es un Objeto como si es una Matriz usando JSON.stringify
:
let myTarget = JSON.parse(JSON.stringify(myProxy))
Este enfoque también funciona con objetivos de matriz, mientras que Object.assign({}, myProxy)
funciona solo si el objetivo es un objeto.
Pero soy muy nuevo en los proxies de JavaScript y mi conocimiento es limitado. Puede que no entienda las limitaciones y advertencias de este enfoque. Sin embargo, ¡tal vez ayude a alguien!
-
Gracias. Esto es lo que necesitaba. Necesitaba el destino de un proxy creado por Vue, para poder pasarlo como parte de una solicitud de recuperación.
–Mike Ryan
23 de enero de 2021 a las 22:24
-
Buena respuesta para versiones anteriores, pero considere toRaw si está en Vue3…
– JL Peyret
1 de noviembre de 2022 a las 7:25
davidiusdadi
Como las otras respuestas ya dijeron un proxy obtener trampa puede ser una solución elegante.
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]
Este ejemplo de código debería ser bastante robusto ya que:
- evita conflictos de nombres de propiedades mediante el uso de un
Symbol
- cubre todos los escenarios de obtención mediante el uso
Reflect.get
en lugar detarget[property]
- ADVERTENCIA: tenga cuidado con la herencia de prototipos: en caso de que su proxy termine siendo utilizado como prototipo, el
not_itself_a_proxy[IDENTITY]
la llamada no regresanot_itself_a_proxy
sino la “identidad” del prototipo!
Hay una forma inteligente de hacer esto: puede agregar un conseguir trap al proxy y hacer que devuelva el objetivo condicionalmente Al igual que..
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);
Recuerde que cuantas más líneas de código agregue a las trampas, más lento será el rendimiento del objeto. Espero que esto ayude.
-
Esta es solo una opción si tiene acceso al código fuente del proxy.
–Leonardo Raele
4 de octubre de 2021 a las 6:13
timkay
Las otras respuestas dieron algunas buenas soluciones. Aquí está la respuesta de @Yuci resumida para las clases, en cuyo caso, es tan simple como definir una variable de instancia de algún nombre especial. La función de obtención del proxy lo devuelve, al igual que el objetivo subyacente.
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__);
-
Esta es solo una opción si tiene acceso al código fuente del proxy.
–Leonardo Raele
4 de octubre de 2021 a las 6:13
¿Qué tal agregar la siguiente trampa de obtención:
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();
Y puede obtener el objetivo del proxy por myProxy.myTarget
:
console.log(myProxy.myTarget) // [0.22089416118932403, 0.08429264462405173]
console.log(myArray === myProxy.myTarget) // true
no puedes Por eso es un proxy. ¿Qué estás tratando de hacer? ¿Por qué necesitas esto?
– Bergi
29 de junio de 2018 a las 7:54
@Bergi Porque si tengo un objeto con referencias circulares, y estas referencias circulares están en proxies, no hay forma de cadena segura mi objeto Obtendré un error de tamaño de pila excedido. 🙁
– Adán
29 de junio de 2018 a las 7:59
¿Puedes hacer un ejemplo de eso, por favor? Referencias circulares (creo que te refieres a esas, no dependencias) debería funcionar bien con proxies, ya que
myProxy === myProxy
aún mantiene. Nada necesita poner sus manos en el objetivo.– Bergi
29 de junio de 2018 a las 8:02