Object.watch () für alle Browser?


118

Bitte beachten Sie, dass Object.Watchund Object.Observesind jetzt beide veraltet (Stand Juni 2018).


Ich suchte nach einer einfachen Möglichkeit, ein Objekt oder eine Variable auf Änderungen zu überwachen, und fand heraus Object.watch(), dass dies in Mozilla-Browsern unterstützt wird, nicht jedoch im IE. Also fing ich an, mich umzusehen, ob jemand eine Entsprechung geschrieben hatte.

Das einzige, was ich gefunden habe, war ein jQuery-Plugin , aber ich bin mir nicht sicher, ob dies der beste Weg ist. Ich verwende jQuery auf jeden Fall in den meisten meiner Projekte, daher mache ich mir keine Sorgen um den jQuery-Aspekt ...

Wie auch immer, die Frage: Kann mir jemand ein funktionierendes Beispiel für dieses jQuery-Plugin zeigen? Ich habe Probleme damit es funktioniert ...

Oder kennt jemand bessere Alternativen, die browserübergreifend funktionieren würden?

Update nach Antworten :

Vielen Dank an alle für die Antworten! Ich habe den hier veröffentlichten Code ausprobiert: http://webreflection.blogspot.com/2009/01/internet-explorer-object-watch.html

Aber ich konnte es scheinbar nicht mit IE zum Laufen bringen. Der folgende Code funktioniert in Firefox einwandfrei, im IE jedoch nicht. In Firefox wird bei jeder watcher.statusÄnderung das document.write()In watcher.watch()aufgerufen und Sie können die Ausgabe auf der Seite sehen. Im IE passiert das nicht, aber ich kann sehen, dass watcher.statusder Wert aktualisiert wird, da der letzte document.write()Aufruf den richtigen Wert anzeigt (sowohl im IE als auch im FF). Aber wenn die Rückruffunktion nicht aufgerufen wird, ist das irgendwie sinnlos ... :)

Vermisse ich etwas

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 können Sie onPropertyChange in IE
scunliffe

1
Ersetzen Sie document.write () durch alert (). Es sollte gut funktionieren.
Ionuț G. Stan

Antworten:


113

(Entschuldigung für das Cross-Posting, aber diese Antwort, die ich auf eine ähnliche Frage gegeben habe, funktioniert hier einwandfrei.)

Ich habe vor einiger Zeit ein kleines Objekt erstellt. Es funktioniert in IE8, Safari, Chrome, Firefox, Opera usw.


10
Eine Erklärung, wie man es benutzt und wie es intern funktioniert, wäre schön für diejenigen von uns, die keine JS-Meister sind, danke.
Maraujop


jsfiddle.net/kSWxP TIPP: Verwenden Sie Firefox (die letztere Aussage ist nicht in Chrome gedruckt)
Mars Robertson


Ich hatte gewusst, dass es eine Idee gibt Object.defineProperty(). Am Ende habe ich mir die MDN- Referenz angesehen, um zu sehen, wie es funktioniert.
Jumpnett

19

Dieses Plugin verwendet einfach einen Timer / ein Intervall, um wiederholt nach Änderungen an einem Objekt zu suchen. Vielleicht gut genug, aber ich persönlich hätte gerne mehr Unmittelbarkeit als Beobachter.

Hier ist ein Versuch, watch/ unwatchzum IE zu bringen: http://webreflection.blogspot.com/2009/01/internet-explorer-object-watch.html .

Es ändert die Syntax gegenüber der Firefox-Methode zum Hinzufügen von Beobachtern. Anstatt :

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

Sie machen:

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

Nicht so süß, aber als Beobachter werden Sie sofort benachrichtigt.


Ja, sehen Sie sich diese Zeitstempel an ... Sie müssen nicht abstimmen, auch crescentfresh hat dem Beitrag weitere Informationen hinzugefügt, selbst wenn es sich um denselben Link handelte. In der Zwischenzeit habe ich den auf dieser Seite gefundenen Code ausprobiert und sehe immer noch ein Problem. Ich kann jedoch etwas übersehen. Ich habe meinen ursprünglichen Beitrag mit weiteren Informationen aktualisiert ...
SeanW

13

Die Antworten auf diese Frage sind etwas veraltet. Object.watch und Object.observe sind beide veraltet und sollten nicht verwendet werden.

Heute können Sie das Proxy- Objekt verwenden, um an einem Objekt vorgenommene Änderungen zu überwachen (und abzufangen). Hier ist ein einfaches Beispiel:

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'

Wenn Sie Änderungen an einem verschachtelten Objekt beobachten müssen, müssen Sie eine spezielle Bibliothek verwenden. Ich habe Observable Slim veröffentlicht und es funktioniert so:

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

Aktuelle Antwort

Verwenden Sie das neue Proxy- Objekt, mit dem Änderungen am Ziel überwacht werden können.

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

Alte Antwort von 2015

Sie hätten Object.observe () von ES7 verwenden können . Hier ist eine Polyfüllung. Aber Object.observe () wird nun abgebrochen . Sorry Leute!


Hm, ich konnte diese Polyfüllung nicht dazu bringen, auf ios safari zu arbeiten. Ich erhalte den Fehler: undefined ist keine Funktion (Auswertung von 'Object.observe (a.imgTouch, Funktion (a) {console.debug ("lastX:" + a)})')
infomofo

@infomofo Hallo, möchten Sie eine Ausgabe auf der Projektseite mit allen Details öffnen, die Sie angeben können? Ich habe es nicht auf iOS getestet, aber ich werde das Problem untersuchen.
MaxArt

6

Beachten Sie, dass Sie in Chrome 36 und höher auch verwenden können Object.observe. Dies ist tatsächlich Teil eines zukünftigen ECMAScript-Standards und keine browserspezifische Funktion wie die von MozillaObject.watch .

Object.observefunktioniert nur mit Objekteigenschaften, ist aber viel leistungsfähiger als Object.watch(was für Debugging-Zwecke gedacht ist, nicht für Produktionszwecke).

var options = {};

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

options.foo = 'bar';

1
Wie im Jahr 2018 ist dies veraltet und wird nicht mehr von allen gängigen Browsern unterstützt
Sergei Panfilov

4

Sie können Object.defineProperty verwenden .

Beobachten Sie die Unterkunft 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
  }
})

Das ist toll! Aber ich würde es abit modifizieren :) Original Setter nicht überschreiben. Ich würde Referenz foo._someObject = foo.someObject
quietbird

einfach und elegant
ßãlãjî

1

Ich habe Watch.js in einem meiner Projekte verwendet. Und es funktioniert gut. Einer der Hauptvorteile der Verwendung dieser Bibliothek ist:

"Mit Watch.JS müssen Sie Ihre Entwicklung nicht ändern."

Das Beispiel ist unten angegeben

//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>

Das ist so einfach!


Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.