Object.watch () para todos los navegadores?

118

Tenga en cuenta que Object.Watchy Object.Observeson a la vez obsoleta ahora (como el junio del 2018).


Estaba buscando una manera fácil de monitorear cambios en un objeto o variable, y encontré Object.watch() que es compatible con los navegadores Mozilla, pero no con IE. Así que comencé a buscar para ver si alguien había escrito algún tipo de equivalente.

Casi lo único que he encontrado ha sido un complemento de jQuery , pero no estoy seguro de si esa es la mejor manera de hacerlo. Ciertamente uso jQuery en la mayoría de mis proyectos, así que no me preocupa el aspecto de jQuery ...

De todos modos, la pregunta: ¿Puede alguien mostrarme un ejemplo funcional de ese complemento de jQuery? Tengo problemas para que funcione ...

O, ¿alguien conoce alguna alternativa mejor que funcione en varios navegadores?

Actualización después de las respuestas :

¡Gracias a todos por las respuestas! Probé el código publicado aquí: http://webreflection.blogspot.com/2009/01/internet-explorer-object-watch.html

Pero parece que no pude hacerlo funcionar con IE. El siguiente código funciona bien en Firefox, pero no hace nada en IE. En Firefox, cada vez que watcher.statusse cambia, se llama a document.write()in watcher.watch()y puedes ver el resultado en la página. En IE, eso no sucede, pero puedo ver que watcher.statusestá actualizando el valor, porque el últimodocument.write() llamada muestra el valor correcto (tanto en IE como en FF). Pero, si no se llama a la función de devolución de llamada, entonces no tiene sentido ... :)

¿Me estoy perdiendo de algo?

var options = {'status': 'no status'},
watcher = createWatcher(options);

watcher.watch("status", function(prop, oldValue, newValue) {
  document.write("old: " + oldValue + ", new: " + newValue + "<br>");
  return newValue;
});

watcher.status = 'asdf';
watcher.status = '1234';

document.write(watcher.status + "<br>");
SeanW
fuente
2
IIRC que puede usar onPropertyChange en IE
scunliffe
1
Reemplace document.write () con alert (). debería funcionar bien.
Ionuț G. Stan

Respuestas:

113

(Lo siento por la publicación cruzada, pero esta respuesta que di a una pregunta similar funciona bien aquí)

He creado un objeto pequeño. Mire la calza para esto hace un tiempo. Funciona en IE8, Safari, Chrome, Firefox, Opera, etc.

Eli Grey
fuente
10
Una explicación sobre cómo usarlo y cómo funciona esto internamente sería bueno para aquellos de nosotros que no somos maestros de JS, gracias.
maraujop
jsfiddle.net/kSWxP SUGERENCIA: use Firefox (la última declaración no está impresa en Chrome)
Mars Robertson
Sabía que la idea Object.defineProperty()existía. Terminé mirando la referencia de MDN para ver cómo funcionaba.
Jumpnett
19

Ese complemento simplemente usa un temporizador / intervalo para verificar repetidamente los cambios en un objeto. Quizás lo suficientemente bueno, pero personalmente me gustaría tener más inmediatez como observador.

Aquí hay un intento de llevar watch/ unwatcha IE: http://webreflection.blogspot.com/2009/01/internet-explorer-object-watch.html .

Cambia la sintaxis de la forma en que Firefox agrega observadores. En vez de :

var obj = {foo:'bar'};
obj.watch('foo', fooChanged);

Tú lo haces:

var obj = {foo:'bar'};
var watcher = createWatcher(obj);
watcher.watch('foo', fooChanged);

No tan dulce, pero como observador, se le notifica de inmediato.

Creciente fresco
fuente
Sí, mire esas marcas de tiempo ... no es necesario votar en contra, también crescentfresh agregó más información a la publicación, incluso si era el mismo enlace. Mientras tanto, probé el código que se encuentra en esa página y todavía veo un problema. Sin embargo, puede que esté pasando por alto algo. He actualizado mi publicación original con más información ...
SeanW
13

Las respuestas a esta pregunta están un poco desactualizadas. Object.watch y Object.observe están en desuso y no deben usarse.

Hoy en día, ahora puede usar el objeto Proxy para monitorear (e interceptar) los cambios realizados en un objeto. Aquí tienes un ejemplo básico:

var targetObj = {};
var targetProxy = new Proxy(targetObj, {
  set: function (target, key, value) {
      console.log(`${key} set to ${value}`);
      target[key] = value;
  }
});

targetProxy.hello_world = "test"; // console: 'hello_world set to test'

Si necesita observar los cambios realizados en un objeto anidado, debe utilizar una biblioteca especializada. Publiqué observable delgado y funciona de esta manera:

var test = {testing:{}};
var p = ObservableSlim.create(test, true, function(changes) {
    console.log(JSON.stringify(changes));
});

p.testing.blah = 42; // console:  [{"type":"add","target":{"blah":42},"property":"blah","newValue":42,"currentPath":"testing.blah",jsonPointer:"/testing/blah","proxy":{"blah":42}}]
Elliot B.
fuente
12

Respuesta actual

Utilice el nuevo objeto Proxy , que puede observar los cambios en su objetivo.

let validator = {
    set: function(obj, prop, value) {
        if (prop === 'age') {
            if (!Number.isInteger(value)) {
                throw new TypeError('The age is not an integer');
            }
            if (value > 200) {
                throw new RangeError('The age seems invalid');
            }
        }

        // The default behavior to store the value
        obj[prop] = value;

        // Indicate success
        return true;
    }
};

let person = new Proxy({}, validator);

person.age = 100;
console.log(person.age); // 100
person.age = 'young'; // Throws an exception
person.age = 300; // Throws an exception

Respuesta anterior de 2015

Podría haber usado Object.observe () de ES7 . Aquí hay un polyfill. Pero Object.observe () ahora está cancelado . ¡Lo siento gente!

mikemaccana
fuente
Hm, no pude hacer que este polyfill funcionara en ios safari. Recibo Error: undefined no es una función (evaluando 'Object.observe (a.imgTouch, function (a) {console.debug ("lastX:" + a)})')
infomofo
@infomofo Hola, ¿te gustaría abrir un problema en la página del proyecto, con todos los detalles que puedes dar? No lo he probado en iOS, pero investigaré el problema.
MaxArt
6

Tenga en cuenta que en Chrome 36 y superior también puede usar Object.observe. En realidad, esto es parte de un futuro estándar ECMAScript, y no una característica específica del navegador como la de Mozilla Object.watch.

Object.observesolo funciona en las propiedades del objeto, pero es mucho más eficiente que Object.watch(lo que está destinado a fines de depuración, no para uso de producción).

var options = {};

Object.observe(options, function(changes) {
    console.log(changes);
});

options.foo = 'bar';
Fornido
fuente
1
Como en 2018, esto está obsoleto y ya no es compatible con todos los navegadores principales
Sergei Panfilov
4

puede utilizar Object.defineProperty .

ver la propiedad barenfoo

Object.defineProperty(foo, "bar", {
  get: function (val){
      //some code to watch the getter function
  },

  set: function (val) {
      //some code to watch the setter function
  }
})
souparno majumder
fuente
¡Esto es genial! Pero lo modificaría un poco :) Para no sobrescribir el setter original. Haría referencia foo._someObject = foo.someObject
calmbird
simple y
elegante
1

He usado Watch.js en uno de mis proyectos. Y está funcionando bien Una de las principales ventajas de usar esta biblioteca es:

"Con Watch.JS no tendrá que cambiar la forma en que se desarrolla".

El ejemplo se da a continuación

//defining our object however we like
var ex1 = {
	attr1: "initial value of attr1",
	attr2: "initial value of attr2"
};

//defining a 'watcher' for an attribute
watch(ex1, "attr1", function(){
	alert("attr1 changed!");
});

//when changing the attribute its watcher will be invoked
ex1.attr1 = "other value";
<script src="https://cdn.jsdelivr.net/npm/[email protected]/src/watch.min.js"></script>

¡Esto es tan simple como esto!

NIKHIL CM
fuente