Object.watch () dla wszystkich przeglądarek?


118

Należy pamiętać, że oba Object.Watchi Object.Observesą obecnie przestarzałe (stan na czerwiec 2018 r.).


Szukałem łatwego sposobu monitorowania obiektu lub zmiennej pod kątem zmian i stwierdziłem Object.watch(), że jest to obsługiwane w przeglądarkach Mozilla, ale nie w IE. Zacząłem więc rozglądać się po okolicy, żeby sprawdzić, czy ktoś napisał jakiś odpowiednik.

Jedyne, co znalazłem, to wtyczka jQuery , ale nie jestem pewien, czy to najlepszy sposób. Z pewnością używam jQuery w większości moich projektów, więc nie martwię się o aspekt jQuery ...

W każdym razie pytanie: Czy ktoś może mi pokazać działający przykład tej wtyczki jQuery? Mam problem, żeby to zadziałało ...

A może ktoś zna lepsze alternatywy, które działałyby w różnych przeglądarkach?

Zaktualizuj po odpowiedziach :

Dziękuję wszystkim za odpowiedzi! Wypróbowałem kod zamieszczony tutaj: http://webreflection.blogspot.com/2009/01/internet-explorer-object-watch.html

Ale nie mogłem sprawić, by działało z IE. Poniższy kod działa dobrze w przeglądarce Firefox, ale nic nie robi w IE. W przeglądarce Firefox za każdym razem, gdy watcher.statusjest zmieniany, wywoływana jest document.write()in watcher.watch()i można zobaczyć wynik na stronie. W IE tak się nie dzieje, ale widzę, że watcher.statusjest to aktualizacja wartości, ponieważ ostatnie document.write()wywołanie pokazuje poprawną wartość (zarówno w IE, jak i FF). Ale jeśli funkcja zwrotna nie zostanie wywołana, to jest to trochę bezcelowe ... :)

Czy coś mi brakuje?

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, którego możesz użyć onPropertyChange w IE
scunliffe

1
Zamień document.write () na alert (). Powinno działać dobrze.
Ionuț G. Stan

Odpowiedzi:


113

(Przepraszam za cross-posting, ale ta odpowiedź, której udzieliłem na podobne pytanie, działa tutaj dobrze)

Stworzyłem mały obiekt. Podkładka do zegarka do tego jakiś czas temu. Działa w IE8, Safari, Chrome, Firefox, Opera itp.


10
Wyjaśnienie, jak go używać i jak to działa wewnętrznie, byłoby miłe dla tych z nas, którzy nie są mistrzami JS, dzięki.
maraujop


jsfiddle.net/kSWxP WSKAZÓWKA: użyj przeglądarki Firefox (ta ostatnia instrukcja nie jest drukowana w przeglądarce Chrome)
Mars Robertson


Wiedziałem, że pomysł Object.defineProperty()istnieje. W końcu spojrzałem na odniesienie do MDN, aby zobaczyć, jak to działa.
Jumpnett

19

Ta wtyczka po prostu używa licznika czasu / interwału do wielokrotnego sprawdzania zmian w obiekcie. Może wystarczająco dobrze, ale osobiście chciałbym mieć większą bezpośredniość jako obserwator.

Oto próba przeniesienia watch/ unwatchdo IE: http://webreflection.blogspot.com/2009/01/internet-explorer-object-watch.html .

To zmienia składnię ze sposobu dodawania obserwatorów w Firefoksie. Zamiast :

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

Ty robisz:

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

Nie tak słodkie, ale jako obserwator jesteś natychmiast powiadamiany.


Tak, uważaj na te znaczniki czasu ... nie trzeba głosować w dół, również crescentfresh dodał więcej informacji do posta, nawet jeśli był to ten sam link. W międzyczasie wypróbowałem kod znaleziony na tej stronie i nadal widzę problem. Chociaż może coś przeoczę. Zaktualizowałem mój oryginalny post o więcej informacji ...
SeanW

13

Odpowiedzi na to pytanie są nieco nieaktualne. Object.watch i Object.observe są przestarzałe i nie powinny być używane.

Obecnie można teraz używać obiektu Proxy do monitorowania (i przechwytywania) zmian wprowadzonych w obiekcie. Oto podstawowy przykład:

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'

Jeśli chcesz obserwować zmiany wprowadzone w zagnieżdżonym obiekcie, musisz użyć specjalistycznej biblioteki. Opublikowałem Observable Slim i działa tak:

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

Aktualna odpowiedź

Użyj nowego obiektu Proxy , który może obserwować zmiany w celu.

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

Stara odpowiedź z 2015 roku

Mogłeś użyć Object.observe () z ES7 . Oto polyfill. Ale Object.observe () jest teraz anulowana . Przepraszam ludzie!


Hm, nie mogłem zmusić tego polyfill do działania na safari na iOS. Otrzymuję błąd: undefined nie jest funkcją (oceniam 'Object.observe (a.imgTouch, function (a) {console.debug ("lastX:" + a)})')
infomofo

@infomofo Cześć, czy chciałbyś otworzyć numer na stronie projektu ze wszystkimi szczegółami, które możesz podać? Nie testowałem tego na iOS, ale przyjrzę się problemowi.
MaxArt

6

Pamiętaj, że w Chrome 36 i nowszych możesz również używać Object.observe. W rzeczywistości jest to część przyszłego standardu ECMAScript, a nie funkcja specyficzna dla przeglądarki, taka jak Mozilla Object.watch.

Object.observedziała tylko na właściwościach obiektu, ale jest dużo bardziej wydajny niż Object.watch(co jest przeznaczone do celów debugowania, a nie do użytku produkcyjnego).

var options = {};

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

options.foo = 'bar';

1
Tak jak w 2018 roku jest to przestarzałe i nie jest już obsługiwane przez wszystkie główne przeglądarki
Sergei Panfilov

4

możesz użyć Object.defineProperty .

oglądać nieruchomość barwfoo

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

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

To jest świetne! Ale trochę bym to zmodyfikował :) Nie nadpisywać oryginalnego setera. Zrobiłbym odniesienie foo._someObject = foo.someObject
calmbird

proste i eleganckie
ßãlãjî

1

Użyłem Watch.js w jednym z moich projektów. I działa dobrze.Jedną z głównych zalet korzystania z tej biblioteki jest:

„Dzięki Watch.JS nie będziesz musiał zmieniać sposobu, w jaki się rozwijasz”.

Przykład podano poniżej

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

To takie proste!


Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.