Object.watch () pour tous les navigateurs?

118

Veuillez noter que Object.Watchet Object.Observesont tous deux obsolètes maintenant (à partir de juin 2018).


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

La seule chose que j'ai trouvée est un plugin jQuery , mais je ne suis pas sûr que ce soit la meilleure façon de procéder. J'utilise certainement jQuery dans la plupart de mes projets, donc je ne suis pas inquiet pour l'aspect jQuery ...

Quoi qu'il en soit, la question: quelqu'un peut-il me montrer un exemple fonctionnel 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?

Mettre à 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 watcher.statusmodification, le document.write()in watcher.watch()est appelé et vous pouvez voir la sortie sur la page. Dans IE, cela ne se produit pas, mais je peux voir que watcher.statusla valeur est mise à jour, car le dernier document.write()appel montre la valeur correcte (à la fois dans IE et FF). Mais si la fonction de rappel n'est pas appelée, c'est un peu inutile ... :)

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>");
SeanW
la source
2
IIRC, vous pouvez utiliser onPropertyChange dans IE
scunliffe
1
Remplacez document.write () par alert (). Il devrait fonctionner parfaitement.
Ionuț G. Stan

Réponses:

113

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

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

Eli Gray
la source
10
Une explication sur la façon de l'utiliser et comment cela fonctionne en interne serait bien pour ceux d'entre nous qui ne sont pas des maîtres JS, merci.
maraujop du
jsfiddle.net/kSWxP CONSEIL: utilisez Firefox (cette dernière déclaration n'est pas imprimée dans Chrome)
Mars Robertson
Je savais que l'idée Object.defineProperty()existait. J'ai fini par regarder la référence MDN pour voir comment cela fonctionnait.
jumpnett
19

Ce plugin utilise simplement un minuteur / intervalle pour vérifier à plusieurs reprises les changements sur un objet. Peut-être assez bien mais personnellement j'aimerais plus d'immédiateté en tant qu'observateur.

Voici une tentative d'amener watch/ unwatchà IE: http://webreflection.blogspot.com/2009/01/internet-explorer-object-watch.html .

Cela change la syntaxe de la manière de Firefox d'ajouter 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.

Croissant frais
la source
Oui, regardez ces horodatages ... pas besoin de voter contre, aussi croissantfresh a ajouté plus d'informations à l'article, même s'il s'agissait du même lien. En attendant, j'ai essayé le code trouvé sur cette page et je vois toujours un problème. J'oublie peut-être quelque chose. J'ai mis à jour mon message d'origine avec plus d'informations ...
SeanW
13

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 désormais 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 avez besoin d'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}}]
Elliot B.
la source
12

Réponse actuelle

Utilisez le nouvel objet Proxy , qui peut surveiller 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 () depuis ES7 . Voici un polyfill. Mais Object.observe () est maintenant annulé . Désolé les gens!

Mikemaccana
la source
Hm, je n'ai pas pu faire fonctionner ce polyfill sur iOS Safari. J'obtiens une erreur: undefined n'est pas une fonction (évaluation de 'Object.observe (a.imgTouch, function (a) {console.debug ("lastX:" + a)})')
infomofo
@infomofo Bonjour, souhaitez-vous ouvrir un numéro sur la page du projet, avec tous les détails que vous pouvez donner? Je ne l'ai pas testé sur iOS, mais je vais examiner le problème.
MaxArt
6

Notez que dans Chrome 36 et supérieur, vous pouvez également l'utiliser Object.observe. C'est en fait une partie d'un futur standard ECMAScript, et non une fonctionnalité spécifique au navigateur comme celle de Mozilla Object.watch.

Object.observene fonctionne que sur les propriétés des objets, mais est beaucoup plus performant que Object.watch(qui est destiné à des fins de débogage, pas à une utilisation en production).

var options = {};

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

options.foo = 'bar';
Rauque
la source
1
Comme en 2018, cela est obsolète et n'est plus pris en charge par tous les principaux navigateurs
Sergei Panfilov
4

vous pouvez utiliser Object.defineProperty .

regarder la propriété bardansfoo

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

  set: function (val) {
      //some code to watch the setter function
  }
})
souparno majumder
la source
C'est bien! Mais je le modifierais un peu :) Pour ne pas écraser le setter d'origine. Je ferais référence à foo._someObject = foo.someObject
calmbird
simple et élégant
ßãlãjî
1

J'ai utilisé Watch.js dans l'un de mes projets. Et cela fonctionne 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!

NIKHIL CM
la source