Object.watch () per tutti i browser?


118

Tieni presente che Object.Watche Object.Observesono entrambi deprecati ora (a partire da giugno 2018).


Stavo cercando un modo semplice per monitorare un oggetto o una variabile per le modifiche e ho scoperto Object.watch()che è supportato nei browser Mozilla, ma non in IE. Così ho iniziato a cercare in giro per vedere se qualcuno avesse scritto una sorta di equivalente.

L'unica cosa che ho trovato è stato un plugin jQuery , ma non sono sicuro che sia il modo migliore per farlo. Sicuramente uso jQuery nella maggior parte dei miei progetti, quindi non sono preoccupato per l'aspetto jQuery ...

Ad ogni modo, la domanda: qualcuno può mostrarmi un esempio funzionante di quel plugin jQuery? Ho problemi a farlo funzionare ...

Oppure qualcuno conosce alternative migliori che funzionerebbero su tutti i browser?

Aggiornamento dopo le risposte :

Grazie a tutti per le risposte! Ho provato il codice pubblicato qui: http://webreflection.blogspot.com/2009/01/internet-explorer-object-watch.html

Ma non riuscivo a farlo funzionare con IE. Il codice seguente funziona bene in Firefox, ma non fa nulla in IE. In Firefox, ogni volta che watcher.statusviene modificato, il document.write()di watcher.watch()si chiama e si può vedere l'output della pagina. In IE, ciò non accade, ma posso vedere che watcher.statussta aggiornando il valore, perché l'ultima document.write()chiamata mostra il valore corretto (sia in IE che in FF). Ma se la funzione di callback non viene chiamata, allora è inutile ... :)

Mi sto perdendo qualcosa?

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>");

2
IIRC puoi usare suPropertyChange in IE
scunliffe

1
Sostituisci document.write () con alert (). Dovrebbe funzionare bene.
Ionuț G. Stan

Risposte:


113

(Ci scusiamo per il cross-posting, ma questa risposta che ho dato a una domanda simile funziona bene qui)

Ho creato un piccolo object.watch shim per questo tempo fa. Funziona in IE8, Safari, Chrome, Firefox, Opera, ecc.


10
Una spiegazione su come usarlo e come funziona internamente sarebbe bello per quelli di noi che non sono maestri di JS, grazie.
maraujop


jsfiddle.net/kSWxP SUGGERIMENTO: usa Firefox (quest'ultima istruzione non è stampata in Chrome)
Mars Robertson


Sapevo che l'idea Object.defineProperty()esistesse. Ho finito per guardare il riferimento MDN per vedere come funzionava.
jumpnett

19

Quel plugin utilizza semplicemente un timer / intervallo per controllare ripetutamente le modifiche su un oggetto. Forse abbastanza buono ma personalmente vorrei più immediatezza come osservatore.

Ecco un tentativo di portare watch/ unwatchsu IE: http://webreflection.blogspot.com/2009/01/internet-explorer-object-watch.html .

Cambia la sintassi dal modo in cui Firefox aggiunge osservatori. Invece di :

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

Tu fai:

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

Non così dolce, ma come osservatore vieni avvisato immediatamente.


Sì, guarda quei timestamp ... non c'è bisogno di downvote, anche crescentfresh ha aggiunto ulteriori informazioni al post, anche se era lo stesso link. Nel frattempo, ho provato il codice trovato in quella pagina e vedo ancora un problema. Potrei però trascurare qualcosa. Ho aggiornato il mio post originale con maggiori informazioni ...
SeanW

13

Le risposte a questa domanda sono un po 'datate. Object.watch e Object.observe sono entrambi deprecati e non devono essere utilizzati.

Oggi è ora possibile utilizzare l' oggetto Proxy per monitorare (e intercettare) le modifiche apportate a un oggetto. Ecco un esempio di base:

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'

Se è necessario osservare le modifiche apportate a un oggetto nidificato, è necessario utilizzare una libreria specializzata. Ho pubblicato Observable Slim e funziona così:

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}}]

12

Risposta attuale

Usa il nuovo oggetto Proxy , che può guardare le modifiche al suo target.

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

Vecchia risposta del 2015

Avresti potuto usare Object.observe () da ES7 . Ecco un polyfill. Ma Object.observe () è ora annullato . Scusate gente!


Hm, non sono riuscito a far funzionare questo polyfill su iOS Safari. Ottengo l'errore: undefined non è una funzione (valutazione di "Object.observe (a.imgTouch, function (a) {console.debug (" lastX: "+ a)}) ')
infomofo

@infomofo Ciao, vorresti aprire un numero nella pagina del progetto, con tutti i dettagli che puoi fornire? Non l'ho provato su iOS, ma esaminerò il problema.
MaxArt

6

Nota che in Chrome 36 e versioni successive puoi usare Object.observeanche. Questa è in realtà una parte di un futuro standard ECMAScript e non una funzionalità specifica del browser come quella di Mozilla Object.watch.

Object.observefunziona solo sulle proprietà degli oggetti, ma è molto più performante di Object.watch(che è pensato per scopi di debug, non per uso di produzione).

var options = {};

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

options.foo = 'bar';

1
Come nel 2018, questo è deprecato e non è più supportato da tutti i principali browser
Sergei Panfilov

4

puoi usare Object.defineProperty .

guarda la proprietà barinfoo

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

  set: function (val) {
      //some code to watch the setter function
  }
})

È fantastico! Ma lo modificherei abit :) Per non sovrascrivere il setter originale. Farei riferimento a foo._someObject = foo.someObject
calmbird

semplice ed
elegante

1

Ho utilizzato Watch.js in uno dei miei progetti. E funziona bene Uno dei principali vantaggi dell'utilizzo di questa libreria è:

"Con Watch.JS non dovrai cambiare il modo in cui ti sviluppi."

L'esempio è fornito di seguito

//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/melanke-watchjs@1.5.0/src/watch.min.js"></script>

È così semplice!


Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.