web-dev-qa-db-fra.com

Object.watch () pour tous les navigateurs?

Veuillez noter que Object.Watch et Object.Observe sont désormais obsolètes (à partir de juin 2018).


Je cherchais un moyen simple de surveiller les modifications apportées à un objet ou à une variable, et j’ai trouvé Object.watch(), qui est pris en charge par les navigateurs Mozilla, mais pas par IE. Alors j'ai commencé à chercher pour voir si quelqu'un avait écrit une sorte d'équivalent.

À propos de la seule chose que j'ai trouvée a été n plugin jQuery , mais je ne suis pas sûr que ce soit la meilleure façon de faire. J'utilise certainement jQuery dans la plupart de mes projets, je ne m'inquiète donc pas pour l'aspect jQuery ...

Quoi qu'il en soit, la question: quelqu'un peut-il me montrer un exemple de travail de ce plugin jQuery? J'ai du mal à le faire fonctionner ...

Ou, est-ce que quelqu'un connaît de meilleures alternatives qui fonctionneraient avec plusieurs navigateurs?

Mise à jour après les réponses :

Merci à tous pour les réponses! J'ai essayé le code posté ici: http://webreflection.blogspot.com/2009/01/internet-Explorer-object-watch.html

Mais je n'arrivais pas à le faire fonctionner avec IE. Le code ci-dessous fonctionne bien dans Firefox, mais ne fait rien dans IE. Dans Firefox, chaque fois que watcher.status Est modifié, la document.write() dans watcher.watch() est appelée et vous pouvez voir la sortie sur la page. Cela ne se produit pas dans IE, mais je peux voir que watcher.status Met à jour la valeur, car le dernier appel de document.write() indique la valeur correcte (dans les deux IE et FF). Mais si la fonction de rappel n’est pas appelée, c’est inutile, alors ... :)

Est-ce que je manque quelque chose?

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

(Désolé pour le commentaire croisé, mais cette réponse que j'ai donnée à une question similaire fonctionne bien ici)

J'ai créé un petit object.watch shim pour cela il y a quelque temps. Cela fonctionne dans IE8, Safari, Chrome, Firefox, Opera, etc.

113
Eli Grey

Ce plugin utilise simplement un minuteur/intervalle pour vérifier de manière répétée les modifications apportées à un objet. Peut-être assez bon mais personnellement, je voudrais plus d’immédiateté en tant qu’observateur.

Voici une tentative pour amener watch/unwatch à IE: http://webreflection.blogspot.com/2009/01/internet-Explorer-object-watch.html =.

Cela modifie la syntaxe par rapport à la façon dont Firefox ajoute des observateurs. Au lieu de :

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

Tu fais:

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

Pas aussi gentil, mais en tant qu'observateur, vous êtes immédiatement averti.

19
Crescent Fresh

Les réponses à cette question sont un peu dépassées. Object.watch et Object.observe sont tous deux obsolètes et ne doivent pas être utilisés.

Aujourd'hui, vous pouvez maintenant utiliser l'objet Proxy pour surveiller (et intercepter) les modifications apportées à un objet. Voici un exemple de 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'

Si vous devez observer les modifications apportées à un objet imbriqué, vous devez utiliser une bibliothèque spécialisée. J'ai publié Observable Slim et cela fonctionne comme ceci:

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
Elliot B.

Réponse actuelle

Utilisez le nouvel objet Proxy , qui peut suivre les modifications apportées à sa cible.

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

Ancienne réponse de 2015

Vous auriez pu utiliser Object.observe () de ES7 . Voici un polyfill. Mais Object.observe () est maintenant annulé . Désolé les gens!

11
mikemaccana

Notez que dans Chrome 36 et supérieur, vous pouvez également utiliser Object.observe . Il s’agit en fait d’une partie d’un futur standard ECMAScript et non d’un navigateur. fonction spécifique comme le Object.watch de Mozilla.

Object.observe Ne fonctionne que sur les propriétés des objets, mais est beaucoup plus performant que Object.watch (Destiné à des fins de débogage et non à une utilisation en production).

var options = {};

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

options.foo = 'bar';
6
Husky

vous pouvez utiliser Object.defineProperty .

regarder la propriété bar dans 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
  }
})
2
souparno majumder

J'ai utilisé Watch.js dans l'un de mes projets. Et cela fonctionne très bien. L’un des principaux avantages de l’utilisation de cette bibliothèque est:

"Avec Watch.JS, vous n’aurez pas à changer votre façon de vous développer."

L'exemple est donné ci-dessous

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

C'est aussi simple que ça!

1
NIKHIL C M