2012-07-23 5 views
102

Firebug für firefox hat eine nette Funktion namens "Break on property change", wo ich jede Eigenschaft eines Objekts markieren kann, und es wird Javascript Ausführung vor der Änderung zu stoppen.Wie "brechen auf Eigenschaft ändern" in Chrom?

Ich versuche, das gleiche in Google Chrome zu erreichen, und ich kann die Funktion in Chrome Debugger nicht finden. Wie mache ich das in Google Chrome?

+1

Wenn Sie diese Elemente mit HTML zu tun, sehen http://stackoverflow.com/a/32686203/308851 – chx

Antwort

65

Wenn es Ihnen nichts ausmacht, mit der Quelle herumzualbern, könnten Sie die Eigenschaft mit einem Accessor neu definieren.

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

gibt es einen Stecker, in dem das für mich tun würde? –

+3

@ArsenZahray, weiß nicht. Sie können jedoch eine praktische Funktion daraus machen und wie 'console.watch (obj, 'someProp')' 'verwenden. – katspaugh

+2

Dies funktioniert aus Sicherheitsgründen nicht für integrierte Eigenschaften wie 'window.location'. – qJake

94

bearbeiten 2016,03: Object.observe ist veraltet und entfernt in Chrome 50

bearbeiten 2014,05: Object.observe in Chrome 36

Chrome 36 Schiffe mit nativer Object.observe Umsetzung hinzugefügt wurde das kann hier eingesetzt werden:

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

Wenn Sie es nur vorübergehend wollen, sollten Sie Rückruf in einer Variablen speichern und Object.unobserve rufen, wenn Sie fertig:

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

Beachten Sie, dass, wenn Object.observe verwenden, werden Sie nicht benachrichtigt, wenn die Zuordnung nicht irgendetwas geändert hat , z.B wenn Sie myObj.a = 1 geschrieben haben.

den Call-Stack, um zu sehen, müssen Sie "Asynchron-Call-Stack" -Option in Dev-Tools aktivieren:

chrome async call stack


Original-Antwort (2012.07):

A console.watch Skizze wie von @ Katspaugh vorgeschlagen:

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

Invocation:

console.watch(obj, "someProp"); 

Kompatibilität:

  • In Chrome 20, können Sie es direkt in Dev-Tools zur Laufzeit einfügen!
  • Der Vollständigkeit halber: in Firebug 1.10 (Firefox 14) müssen Sie es in Ihre Website injizieren (z. B. via Fiddler, wenn Sie die Quelle nicht manuell bearbeiten können); Leider scheinen die von Firebug definierten Funktionen nicht auf debugger zu brechen (oder ist es eine Frage der Konfiguration? Bitte korrigieren Sie mich dann), aber console.log funktioniert.

Edit:

Beachten Sie, dass in Firefox, console.watch bereits vorhanden ist, aufgrund von Firefox Nicht-Standard-Object.watch.Daher in Firefox können Sie für Änderungen sehen nativ:

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

jedoch this will be soon (late 2017) removed.

+0

Danke, sehr nett! – katspaugh

+1

Es scheint übrigens, dass es nicht möglich ist, den Debugger in benutzerdefiniertem Code zu treffen, eine Regression zwischen Firebug 1.8 und 1.9: [Problem 5757] (http://code.google.com/p/fbug/issues/detail?id=5757)) -> Duplikat von [Problem 5221] (http://code.google.com/p/fbug/issues/detail?id=5221) –

+0

Dies ist sehr hilfreich! – Wint

46

Es gibt eine Bibliothek dafür: BreakOn()

Wenn Sie es auf Chrome Entwickler-Tools als Snippet hinzufügen (Quellen -> Snippets -> Rechtsklick -> neu -> Paste this), können Sie es jederzeit verwenden.


Um es zu verwenden, öffnen Sie die Dev-Tools und führen Sie das Snippet. Dann zu brechen, wenn myObject.myProperty geändert wird, rufen Sie diese aus der Entwickler-Konsole:

breakOn(myObject, 'myProperty'); 

Sie könnten auch die Bibliothek zu einem Projekt Debug-Build hinzufügen, so brauchen Sie nicht breakOn rufen wieder jedes Mal, wenn Sie die refresh Seite.

+2

Brilliant! Funktioniert für mich auf Google Chrome 52.0.2743.116. –

+2

Fantastisch! Ich war überrascht, dass es sogar funktioniert mit 'breakOn (myElement.style, 'transform')' für mich, Chrome 56. –

+1

Funktioniert auf Chrome 60.0.3112.90 mit BreakOn (myInputElement, 'Wert'). –

0

Dies kann auch mithilfe des neuen Objekts Proxy erfolgen, dessen Zweck genau darin besteht, die Lese- und Schreibvorgänge für das Objekt abzufangen, das vom Proxy umschlossen ist. Sie wickeln einfach das Objekt, das Sie beobachten möchten, in einen Proxy und verwenden das neue umgebrochene Objekt anstelle des ursprünglichen.

Beispiel:

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

Jetzt wrappedObject verwenden, wo Sie den Call-Stack originalObject statt und untersuchen auf Pause liefern würde.

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