objetos - proxy javascript
Por qué se ha desaprobado Object.observe() (3)
Descargo de responsabilidad: soy el autor de la biblioteca object-observer que se sugiere a continuación.
No iría con la solución de getters / setters: es complicada, no escalable y no se puede mantener. Backbone hizo su enlace bidireccional de esa manera y la repetición para que funcione correctamente fue un buen pedazo de código.
Proxies es la mejor manera de lograr lo que necesita, simplemente agregue a los ejemplos anteriores algunos registros y gestión de devolución de llamada y ejecútelos en caso de cambios.
En cuanto a las bibliotecas de polifilina, algunas / la mayoría de ellas se implementaron utilizando "verificación sucia" o técnica de sondeo: no eficiente, no eficiente. Ocasionalmente, este es el caso del polyfill señalado por Nirus arriba.
Yo recomendaría recoger una biblioteca que haga observaciones a través de Proxies. Hay algunos por ahí, object-observer es uno de ellos: escrito exactamente para este caso de uso, utiliza Proxies nativos, proporciona observación de árbol profundo, etc.
¿Hay un enfoque alternativo?
¿Hay alguna otra manera de hacer la detección de cambios en el objeto?
Existe el método Proxy, pero ¿alguien puede decirme cómo puedo lograr esto usando Proxy?
var obj = {
foo: 0,
bar: 1
};
Object.observe(obj, function(changes) {
console.log(changes);
});
obj.baz = 2;
// [{name: ''baz'', object: <obj>, type: ''add''}]
obj.foo = ''hello'';
// [{name: ''foo'', object: <obj>, type: ''update'', oldValue: 0}]
Puede lograr esto con getters y setters.
var obj = {
get foo() {
console.log({ name: ''foo'', object: obj, type: ''get'' });
return obj._foo;
},
set bar(val) {
console.log({ name: ''bar'', object: obj, type: ''set'', oldValue: obj._bar });
return obj._bar = val;
}
};
obj.bar = 2;
// {name: ''baz'', object: <obj>, type: ''set'', oldValue: undefined}
obj.foo;
// {name: ''foo'', object: <obj>, type: ''get''}
Alternativamente, en un navegador con soporte para Proxies, puede escribir una solución más genérica.
var obj = {
foo: 1,
bar: 2
};
var proxied = new Proxy(obj, {
get: function(target, prop) {
console.log({ type: ''get'', target, prop });
return Reflect.get(target, prop);
},
set: function(target, prop, value) {
console.log({ type: ''set'', target, prop, value });
return Reflect.set(target, prop, value);
}
});
proxied.bar = 2;
// {type: ''set'', target: <obj>, prop: ''bar'', value: 2}
proxied.foo;
// {type: ''get'', target: <obj>, prop: ''bar''}
@Dan solución es correcta .
En caso de que desee admitir navegadores que sean bastante antiguos, le sugiero que vaya a polyfill .
o use la API Object.defineProperties que es compatible con IE 9.
var obj = Object.defineProperties({}, {
"foo":{
get:function(){
console.log("Get:"+this.value);
},
set:function(val){
console.log("Set:"+val);
this.value = val;
}
},
"bar":{
get:function(){
console.log("Get:"+this.value);
},
set:function(val){
console.log("Set:"+val);
this.value = val;
}
}
});