2012-07-23 16 views
102

Firebug para Firefox tiene una característica agradable, llamada "Interrupción en el cambio de propiedad", donde puedo marcar cualquier propiedad de cualquier objeto, y se detendrá la ejecución de JavaScript justo antes del cambio.¿Cómo "romper con el cambio de propiedad" en cromo?

Estoy tratando de lograr lo mismo en google chrome, y no puedo encontrar la función en el depurador de Chrome. ¿Cómo hago esto en google chrome?

+1

Si desea hacer esto con los elementos HTML ver http://stackoverflow.com/a/32686203/308851 – chx

Respuesta

65

Si no te importa jugar con la fuente, puedes redefinir la propiedad con un descriptor de acceso.

// 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; 
    } 
}); 
+2

es que hay un enchufe en el que hacer eso por mí? –

+3

@ArsenZahray, dunno. Sin embargo, puede hacer una función útil y usar como 'console.watch (obj, 'someProp')'. – katspaugh

+2

Esto no funciona para propiedades integradas como 'window.location' por razones de seguridad. – qJake

94

Editar 2016,03: Object.observe es obsoleto y eliminado en Chrome 50

Editar 2014,05: Object.observe se añadió en Chrome 36

Chrome 36 barcos con Object.observe implementación nativa que puede aproveche aquí:

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

Si desea que sólo temporalmente, debe almacenar de devolución de llamada en una variable y llamar Object.unobserve cuando se hace:

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

Tenga en cuenta que cuando se utiliza Object.observe, usted no notificará cuando la tarea no cambia nada , p.ej si ha escrito myObj.a = 1.

Para ver la pila de llamadas, necesita habilitar la opción "asíncrono pila de llamadas" en Herramientas de desarrollo:

chrome async call stack


Respuesta original (2012.07):

Un boceto de console.watch según lo sugerido por @katspaugh:

console = console || {}; // just in case 
console.watch = function(oObj, sProp) { 
    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; 
     } 
    }); 
} 

Invocación:

console.watch(obj, "someProp"); 

Compatibilidad:

  • En Chrome 20, se puede pegar directamente en Herramientas de desarrollo en tiempo de ejecución!
  • Para completar: en Firebug 1.10 (Firefox 14), debe insertarlo en su sitio web (por ejemplo, a través de Fiddler si no puede editar la fuente manualmente); lamentablemente, las funciones definidas de Firebug no parecen romperse en debugger (¿o es una cuestión de configuración? Corrígeme entonces), pero console.log funciona.

Editar:

Tenga en cuenta que en Firefox, console.watch ya existe, debido a Firefox no estándar Object.watch.De ahí que en Firefox, se puede observar los cambios de forma nativa:

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

Sin embargo, this will be soon (late 2017) removed.

+0

¡Gracias, muy bien! – katspaugh

+1

Por cierto, parece que no se puede acceder al depurador en el código personalizado es una regresión entre Firebug 1.8 y 1.9: [problema 5757] (http://code.google.com/p/fbug/issues/detail?id=5757) -> duplicado de [problema 5221] (http://code.google.com/p/fbug/issues/detail?id=5221) –

+0

¡Esto es de gran ayuda! – Wint

46

Hay una biblioteca para esto: BreakOn()

Si se agrega a las herramientas de Chrome dev como un fragmento (fuentes -> fragmentos -> clic derecho -> Nuevo -> pasta this), puede usarlo en cualquier momento.


Para utilizarlo, abra las herramientas de desarrollo y ejecute el fragmento. Luego de romper cuando se cambia myObject.myProperty, llamar a esto desde el dev-consola:

breakOn(myObject, 'myProperty'); 

También puede añadir la biblioteca de depuración y construcción de su proyecto, de modo que no es necesario llamar a breakOn de nuevo cada vez que se actualiza la página.

+2

¡Brillante! Funciona para mí en Google Chrome 52.0.2743.116. –

+2

¡Fantástico! Me sorprendió que incluso funcionara con 'breakOn (myElement.style, 'transform')' para mí, Chrome 56. –

+1

Funciona en Chrome 60.0.3112.90 con breakOn (myInputElement, 'value'). –

0

Esto también se puede hacer utilizando el nuevo objeto Proxy, cuyo propósito es exactamente eso: interceptar las lecturas y escrituras en el objeto envuelto por el Proxy. Simplemente envuelve el objeto que desea observar en un Proxy y utiliza el nuevo objeto envuelto en lugar del original.

Ejemplo:

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); 

Ahora usa wrappedObject donde se suministraría originalObject lugar y examinar la pila de llamadas en las vacaciones.

0
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; 
    } 
    }); 
} 
Cuestiones relacionadas