javascript - ¿Por qué no funciona Proxy para un objeto Map en ES2015?
google-chrome dictionary (1)
La razón por la que obtiene el error es que el proxy no se involucra en la llamada
p1.set
(aparte de eso, la trampa
set
, no relacionada, a pesar del mismo nombre, se llama para recuperar la referencia de función).
Entonces, una vez que se ha recuperado la referencia de función, se llama con
this
conjunto al proxy, no al
Map
, que
Map
no le gusta.
Si realmente está tratando de interceptar todas las llamadas de acceso a la propiedad en el
Map
, puede solucionarlo vinculando las referencias de funciones de las que está volviendo a
get
(vea las líneas
***
):
var loggingProxyHandler = {
"get" : function(targetObj, propName, receiverProxy) {
let ret = Reflect.get(targetObj, propName, receiverProxy);
console.log("get("+propName.toString()+"="+ret+")");
if (typeof ret === "function") { // ***
ret = ret.bind(targetObj); // ***
} // ***
return ret;
},
"set" : function(targetObj, propName, propValue, receiverProxy) {
console.log("set("+propName.toString()+"="+propValue+")");
return Reflect.set(targetObj, propName, propValue, receiverProxy);
}
};
function onRunTest()
{
let m1 = new Map();
let p1 = new Proxy(m1, loggingProxyHandler);
p1.set("a", "aval");
console.log(p1.get("a")); // "aval"
}
onRunTest();
NOTE: Requires a browser supporting ES2015''s Proxy
Sin embargo, si su objetivo es interceptar
Map#get
y
Map#set
, no necesita un proxy en absoluto.
Ya sea:
-
Cree una subclase de
Map
y ejemplifique eso. Sin embargo, se supone que controla la creación de la instancia deMap
. -
Cree un nuevo objeto que herede de la instancia de
Map
y anuleget
yset
; no tiene que tener el control de la creación delMap
original. -
Reemplace el
set
yget
métodos en la instancia deMap
con sus propias versiones.
Aquí está el # 1:
class MyMap extends Map {
set(...args) {
console.log("set called");
return super.set(...args);
}
get(...args) {
console.log("get called");
return super.get(...args);
}
}
const m1 = new MyMap();
m1.set("a", "aval");
console.log(m1.get("a"));
# 2:
const m1 = new Map();
const p1 = Object.create(m1, {
set: {
value: function(...args) {
console.log("set called");
return m1.set(...args);
}
},
get: {
value: function(...args) {
console.log("get called");
return m1.get(...args);
}
}
});
p1.set("a", "aval");
console.log(p1.get("a"));
# 3:
const m1 = new Map();
const m1set = m1.set; // Yes, we know these are `Map.prototype.set` and
const m1get = m1.get; // `get`, but in the generic case, we don''t necessarily
m1.set = function(...args) {
console.log("set called");
return m1set.apply(m1, args);
};
m1.get = function(...args) {
console.log("get called");
return m1get.apply(m1, args);
}
m1.set("a", "aval");
console.log(m1.get("a"));
Estoy ejecutando el siguiente script a través de la versión 57.0.2987.133 de Google Chrome:
var loggingProxyHandler = {
"get" : function(targetObj, propName, receiverProxy) {
let ret = Reflect.get(targetObj, propName, receiverProxy);
console.log("get("+propName.toString()+"="+ret+")");
return ret;
},
"set" : function(targetObj, propName, propValue, receiverProxy) {
console.log("set("+propName.toString()+"="+propValue+")");
return Reflect.set(targetObj, propName, propValue, receiverProxy);
}
};
function onRunTest()
{
let m1 = new Map();
let p1 = new Proxy(m1, loggingProxyHandler);
p1.set("a", "aval"); // Exception thrown from here
}
onRunTest();
NOTE: Requires a browser supporting ES2015''s Proxy
Cuando se ejecuta, veo que se llama a get trap del controlador para devolver la función de configuración del Mapa y luego recibo el siguiente error:
"Uncaught TypeError: Method Map.prototype.set called on incompatible receiver [object Object]"
at Proxy.set (native)
...
Intenté eliminar las funciones trap del loggingProxyHandler (convirtiéndolo en un objeto vacío) pero aún recibo el mismo error.
Comprendí que se suponía que un objeto Proxy podía generarse para todos los objetos JavaScript ES5 y ES2015 nativos.
La matriz parece funcionar bien bajo el mismo controlador proxy.
¿Entendí mal las especificaciones?
¿A mi código le falta algo?
¿Hay algún error conocido en Chrome?
(Hice una búsqueda y no encontré defectos para Chrome en este tema).