Object.watch () для всіх браузерів?


118

Зверніть увагу , що Object.Watchі Object.Observeобидва засуджується в даний час (за станом на червень 2018 року).


Я шукав простий спосіб моніторингу об'єкта чи змінної для змін, і я виявив Object.watch(), що це підтримується в браузерах Mozilla, але не IE. Тому я почав шукати навколо, щоб побачити, чи хтось написав якийсь еквівалент.

Про єдине, що я знайшов, це плагін jQuery , але я не впевнений, чи це найкращий шлях. Я, звичайно, використовую jQuery у більшості своїх проектів, тому я не переживаю за аспект jQuery ...

У будь-якому випадку питання: Чи може хтось показати мені робочий приклад цього плагіна jQuery? У мене виникають проблеми з його роботою ...

Або хтось знає про якісь кращі альтернативи, які б працювали між браузерами?

Оновлення після відповідей :

Дякую всім за відповіді! Я випробував код, розміщений тут: http://webreflection.blogspot.com/2009/01/internet-explorer-object-watch.html

Але я не міг, здається, змусити його працювати з IE. Код нижче добре працює у Firefox, але нічого не робить в IE. У Firefox, кожен раз , коли watcher.statusзмінюється, document.write()в watcher.watch()називається , і ви можете побачити результат на сторінці. У IE цього не відбувається, але я бачу, що watcher.statusце оновлення значення, оскільки останній document.write()виклик показує правильне значення (і в IE, і в FF). Але якщо функція зворотного дзвінка не викликається, то це безглуздо ... :)

Я щось пропускаю?

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 ви можете використовувати onPropertyChange в IE
scunliffe

1
Замініть document.write () на попередження (). Це повинно працювати чудово.
Ionuț G. Stan

Відповіді:


113

(Вибачте за перехресне повідомлення, але ця відповідь, яку я дав на подібне запитання, працює чудово тут)

Я створив для цього невеликий object.watch shim для цього. Він працює в IE8, Safari, Chrome, Firefox, Opera тощо.


10
Пояснення, як його використовувати та як це працює всередині, було б приємно для тих із нас, хто не є майстрами JS, дякую.
maraujop


jsfiddle.net/kSWxP Підказка: використовуйте Firefox (остання заява не надрукована в Chrome)
Mars Robertson


Я знав, що ідея Object.defineProperty()існує. Я переглянув посилання MDN, щоб побачити, як це працює.
jumpnett

19

Цей плагін просто використовує таймер / інтервал для багаторазової перевірки змін на об'єкті. Можливо, досить добре, але особисто мені хотілося б більше безпосередності як спостерігача.

Ось спроба залучення watch/ unwatchдо IE: http://webreflection.blogspot.com/2009/01/internet-explorer-object-watch.html .

Це змінює синтаксис від способу додавання спостерігачів Firefox. Замість :

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

Ти робиш:

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

Не такий милий, але як спостерігач вас негайно повідомляють.


Так, дивіться ці часові позначки ... не потрібно зволікати, також crescentfresh додав більше інформації до публікації, навіть якщо це було те саме посилання. Тим часом я спробував код, знайдений на цій сторінці, і все ще бачу проблему. Я, можливо, щось не помічаю. Я оновив свій початковий пост з додатковою інформацією ...
SeanW

13

Відповіді на це питання трохи застаріли. Object.watch та Object. спостерігати як застарілі, так і не повинні використовуватися.

Сьогодні ви можете використовувати об’єкт Proxy для контролю (і перехоплення) змін, внесених до об'єкта. Ось основний приклад:

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'

Якщо вам потрібно спостерігати за змінами, внесеними до вкладеного об'єкта, вам потрібно скористатися спеціалізованою бібліотекою. Я опублікував Observable Slim, і він працює так:

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

Поточна відповідь

Використовуйте новий об'єкт проксі , який може спостерігати за змінами цілі.

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

Стара відповідь з 2015 року

Ви могли використовувати Object.observe () від ES7 . Ось поліфіл. Але Object.observe () тепер скасовується . Вибачте людей!


Гм, мені не вдалося змусити цю поліфункцію працювати на ios safari. Я отримую помилку: undefined не є функцією (оцінюючи 'Object.observe (a.imgTouch, function (a) {console.debug ("lastX:" + a)}) ")
infomofo

@infomofo Привіт, ви хочете відкрити випуск на сторінці проекту зі всіма деталями, які ви можете надати? Я не перевіряв його на iOS, але розберуся в проблемі.
MaxArt

6

Зауважте, що в Chrome 36 і новіших версіях ви також можете використовувати Object.observe. Це насправді частина майбутнього стандарту ECMAScript, а не особливості браузера, як Mozilla Object.watch.

Object.observeпрацює лише над властивостями об'єкта, але набагато ефективніше, ніж це Object.watch(призначене для налагодження, а не використання виробництва).

var options = {};

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

options.foo = 'bar';

1
Оскільки у 2018 році це застаріло і більше не підтримується всіма основними браузерами
Сергій Панфілов

4

ви можете використовувати Object.defineProperty .

дивитися майно barвfoo

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

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

Це чудово! Але я би змінив це abit :) Щоб не перезаписати оригінальний сетер. Я б зробив посилання foo._someObject = foo.someObject
calmbird

простий та елегантний
ßãlãjî

1

Я використовував Watch.js в одному зі своїх проектів. І це працює чудово. Однією з головних переваг використання цієї бібліотеки є:

"За допомогою Watch.JS вам не доведеться змінювати спосіб розвитку."

Приклад наведено нижче

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

Це так просто, як це!


Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.