admin管理员组文章数量:1135111
Firebug for Firefox has a nice feature, called "Break on property change", where I can mark any property of any object, and it will stop JavaScript execution right before the change.
I'm trying to achieve the same in Google Chrome, and I can't find the function in Chrome debugger. How do I do this in Google Chrome?
Firebug for Firefox has a nice feature, called "Break on property change", where I can mark any property of any object, and it will stop JavaScript execution right before the change.
I'm trying to achieve the same in Google Chrome, and I can't find the function in Chrome debugger. How do I do this in Google Chrome?
Share Improve this question edited Sep 4, 2018 at 20:28 Alexander Abakumov 14.5k16 gold badges96 silver badges132 bronze badges asked Jul 23, 2012 at 18:26 Arsen ZahrayArsen Zahray 25.3k50 gold badges140 silver badges232 bronze badges 1- 1 If you want to do this with HTML elements see stackoverflow.com/a/32686203/308851 – chx Commented Sep 21, 2015 at 2:09
8 Answers
Reset to default 142If you don't mind messing around with the source, you could redefine the property with an accessor.
// 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;
}
});
There is a library for this: BreakOn()
If you add it to Chrome dev tools as a snippet (sources --> snippets --> right-click --> new --> paste this --> run), you can use it anytime.
To use it, open the dev-tools and run the snippet. Then to break when myObject.myProperty
is changed, call this from the dev-console:
breakOn(myObject, 'myProperty');
You could also add the library to your project's debug-build so you don't need to call breakOn
again every time you refresh the page.
Edit 2016.03: Object.observe
is deprecated and removed in Chrome 50
Chrome 36 ships with native Object.observe
implementation that can be leveraged here:
myObj = {a: 1, b: 2};
Object.observe(myObj, function (changes){
console.log("Changes:");
console.log(changes);
debugger;
})
myObj.a = 42;
If you want it only temporarily, you should store callback in a variable and call Object.unobserve
when done:
myObj = {a: 1, b: 2};
func = function() {debugger;}
Object.observe(myObj, func);
myObj.a = 42;
Object.unobserve(myObj, func);
myObj.a = 84;
Note that when using Object.observe
, you'll not be notified when the assignment didn't change anything, e.g. if you've written myObj.a = 1
.
To see the call stack, you need to enable "async call stack" option in Dev Tools:
Original answer (2012.07):
A console.watch
sketch as suggested by @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");
Compatibility:
- In Chrome 20, you can paste it directly in Dev Tools at runtime!
- For completeness: in Firebug 1.10 (Firefox 14), you have to inject it in your website (e.g. via Fiddler if you can't edit the source manually); sadly, functions defined from Firebug don't seem to break on
debugger
(or is it a matter of configuration? please correct me then), butconsole.log
works.
>>> var obj = { foo: 42 }
>>> obj.watch('foo', function() { console.log('changed') })
>>> obj.foo = 69
changed
69
Edit: Object.watch
was removed in Firefox 57.
This can also be done by using the new Proxy object whose purpose is exactly that: intercepting the reads and writes to the object that is wrapped by the Proxy. You simply wrap the object you would like to observe into a Proxy and use the new wrapped object instead of your original one.
Example:
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);
Now use wrappedObject where you would supply originalObject instead and examine the call stack on break.
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;
}
});
}
Decided to write my own version of this solution, save it in a snippet in Chrome's DevTools, and wrapped it in an IIFE that should support both Node and Browsers. Also changed the observer to use a scope variable rather than a property on the object, such that there is no possibility of name clashes, and any code that enumerates keys will not "see" the new "private key" that is created:
(function (global) {
global.observeObject = (obj, prop) => {
let value
Object.defineProperty(obj, prop, {
get: function () {
return value
},
set: function (newValue) {
debugger
value = newValue
},
})
}
})(typeof process !== 'undefined' ? process : window)
Building on the excellent solution by Alexandos Katechis, here is a version of the snippet that does not disturb the original value of the property. I renamed it to better match what I'm thinking when I use it.
Usage:
- Add the snippet via Sources -> Snippets
- When needed, press Command-O and choose to run the breakOnChange snippet
- Call
breakOnChange(anyObject, 'propertyName')
in the console - Take the action that causes the change
- Stops in debugger
This is very helpful for spotting things like a global library such as jQuery being stomped on by a third-party script.
(function (global) {
global.breakOnChange = (obj, prop) => {
let value = obj[prop]
Object.defineProperty(obj, prop, {
get: function () {
return value
},
set: function (newValue) {
debugger
value = newValue
},
})
}
})(typeof process !== 'undefined' ? process : window)
Chrome has this feature built-in in latest versions https://developers.google.com/web/updates/2015/05/view-and-change-your-dom-breakpoints.
So no more needs for custom libraries and solutions, just right click on DOM element in the inspector and choose 'Break on' -> 'attribute modifications' and that's it.
本文标签: javascriptBreakpoint on property changeStack Overflow
版权声明:本文标题:javascript - Breakpoint on property change - Stack Overflow 内容由网友自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:http://www.betaflare.com/web/1736757941a1951388.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
发表评论