186 votes

Point d'arrêt sur changement de propriété

Firebug pour Firefox dispose d'une fonctionnalité intéressante, appelée "Break on property change", qui me permet de marquer n'importe quelle propriété de n'importe quel objet et d'arrêter l'exécution du JavaScript juste avant le changement.

J'essaie de réaliser la même chose dans Google Chrome, et je ne trouve pas la fonction dans le débogueur de Chrome. Comment puis-je faire cela dans Google Chrome ?

140voto

katspaugh Points 6110

Si cela ne vous dérange pas de manipuler la source, vous pouvez redéfinir la propriété avec un accesseur.

// original object
var obj = {
    someProp: 10
};

// save in another property
obj._someProp = obj.someProp;

// overwrite with accessor
Object.defineProperty(obj, 'someProp', {
    get: function () {
        return obj._someProp;
    },

    set: function (value) {
        debugger; // sets breakpoint
        obj._someProp = value;
    }
});

119voto

jakub.g Points 3734

Edit 2016.03 : Object.observe est déprécié et supprimé dans Chrome 50

~~**Modification 2014.05 : `Object.observe` a été ajouté dans Chrome 36**.

Chrome 36 est doté d'une fonction native Object.observe qui peut être exploitée ici :

myObj = {a: 1, b: 2};
Object.observe(myObj, function (changes){
    console.log("Changes:");
    console.log(changes);
    debugger;
})
myObj.a = 42;

Si vous ne le voulez que temporairement, vous devriez stocker le callback dans une variable et appeler Object.unobserve une fois terminé :

myObj = {a: 1, b: 2};
func = function() {debugger;}
Object.observe(myObj, func);
myObj.a = 42;
Object.unobserve(myObj, func);
myObj.a = 84;

Notez que lorsque vous utilisez Object.observe vous ne serez pas notifié si l'affectation n'a rien changé, par exemple si vous avez écrit myObj.a = 1 .

Pour voir la pile d'appels, vous devez activer l'option "async call stack" dans Dev Tools :

~~

chrome async call stack


Réponse originale (2012.07) :

A console.watch croquis comme suggéré par @katspaugh :

var console = console || {}; // just in case
console.watch = function(oObj, sProp) {
   var sPrivateProp = "$_"+sProp+"_$"; // to minimize the name clash risk
   oObj[sPrivateProp] = oObj[sProp];

   // overwrite with accessor
   Object.defineProperty(oObj, sProp, {
       get: function () {
           return oObj[sPrivateProp];
       },

       set: function (value) {
           //console.log("setting " + sProp + " to " + value); 
           debugger; // sets breakpoint
           oObj[sPrivateProp] = value;
       }
   });
}

Invocation :

console.watch(obj, "someProp");

Compatibilité :

  • Dans Chrome 20, vous pouvez le coller directement dans Dev Tools au moment de l'exécution !
  • Pour être complet : dans Firebug 1.10 (Firefox 14), vous devez l'injecter dans votre site web (par exemple via Fiddler si vous ne pouvez pas éditer la source manuellement) ; malheureusement, les fonctions définies depuis Firebug ne semblent pas se briser sur debugger (ou est-ce une question de configuration ? Veuillez me corriger dans ce cas), mais console.log travaux.

~~Notez que dans Firefox, `console.watch` existe déjà, à cause du [`Object.watch`] non standard de Firefox (https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global\_Objects/Object/watch). Ainsi, dans Firefox, vous pouvez surveiller les changements de manière native :

>>> var obj = { foo: 42 }
>>> obj.watch('foo', function() { console.log('changed') })
>>> obj.foo = 69
changed
69~~ 

Edit : Object.watch a été supprimé dans Firefox 57.

118voto

Il existe une bibliothèque pour cela : BreakOn()

Si vous l'ajoutez aux outils de développement de Chrome en tant que snippet (sources --> bribes d'informations --> clic droit --> nouveau --> coller ce --> exécuter) vous pouvez l'utiliser à tout moment.

enter image description here


Pour l'utiliser, ouvrez les dev-tools et exécutez le snippet. Ensuite, pour casser lorsque myObject.myProperty est modifié, appelez ceci depuis la console de développement :

breakOn(myObject, 'myProperty');

Vous pouvez également ajouter la bibliothèque à la compilation de débogage de votre projet afin de ne pas avoir à faire appel à breakOn à chaque fois que vous rafraîchissez la page.

6voto

Dmitry S. Points 274

Cela peut également être fait en utilisant la nouvelle Proxy dont le but est exactement le même : intercepter les lectures et les écritures dans l'objet qui est enveloppé par le Proxy. Il vous suffit d'envelopper l'objet que vous souhaitez observer dans un Proxy et d'utiliser le nouvel objet enveloppé à la place de l'objet original.

Exemple :

const originalObject = {property: 'XXX', propertyToWatch: 'YYY'};
const watchedProp = 'propertyToWatch';
const handler = {
  set(target, key, value) {
    if (key === watchedProp) {
      debugger;
    }
    target[key] = value;
  }
};
const wrappedObject = new Proxy(originalObject, handler);

Utilisez maintenant wrappedObject là où vous auriez fourni originalObject à la place et examinez la pile d'appels à la rupture.

5voto

Roland Soós Points 522
function debugProperty(obj, propertyName) {
  // save in another property
  obj['_' + propertyName] = obj[propertyName];

  // overwrite with accessor
  Object.defineProperty(obj, propertyName, {
    get: function() {
      return obj['_' + propertyName];
    },

    set: function(value) {
      debugger; // sets breakpoint
      obj['_' + propertyName] = value;
    }
  });
}

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X