Javascript 属性更改的断点
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/11618278/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Breakpoint on property change
提问by Arsen Zahray
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.
Firebug for Firefox 有一个很好的功能,称为“中断属性更改”,我可以在其中标记任何对象的任何属性,并且它会在更改之前立即停止 JavaScript 执行。
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?
我正在尝试在 Google Chrome 中实现相同的功能,但在 Chrome 调试器中找不到该功能。如何在 Google Chrome 中执行此操作?
采纳答案by katspaugh
If 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;
}
});
回答by jakub.g
Edit 2016.03: Object.observe
is deprecated and removed in Chrome 50
编辑 2016.03:Object.observe
在 Chrome 50 中已弃用并删除
Edit 2014.05: Object.observe
was added in Chrome 36
编辑 2014.05:Object.observe
已在 Chrome 36 中添加
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:
Chrome 36 附带了Object.observe
可在此处利用的本机实现:
myObj = {a: 1, b: 2};
Object.observe(myObj, function (changes){
console.log("Changes:");
console.log(changes);
debugger;
})
myObj.a = 42;
如果你只是暂时想要它,你应该将回调存储在一个变量中并Object.unobserve
在完成后调用:
myObj = {a: 1, b: 2};
func = function() {debugger;}
Object.observe(myObj, func);
myObj.a = 42;
Object.unobserve(myObj, func);
myObj.a = 84;
请注意,在使用 时Object.observe
,当分配没有更改任何内容时,您将不会收到通知,例如,如果您已编写myObj.a = 1
.
要查看调用堆栈,您需要在开发工具中启用“异步调用堆栈”选项:
Original answer (2012.07):
原答案(2012.07):
A console.watch
sketch as suggested by @katspaugh:
一个console.watch
由@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.
- 在 Chrome 20 中,您可以在运行时直接将其粘贴到 Dev Tools 中!
- 为完整起见:在 Firebug 1.10 (Firefox 14) 中,您必须将其注入您的网站(例如,如果您无法手动编辑源代码,则通过 Fiddler);可悲的是,从 Firebug 定义的函数似乎没有中断
debugger
(或者是配置问题?请纠正我),但console.log
有效。
Edit:
编辑:
Note that in Firefox, console.watch
already exists, due to Firefox's non-standard Object.watch
. Hence in Firefox, you can watch for changes natively:
请注意,在 Firefox 中,console.watch
由于 Firefox 的非标准Object.watch
. 因此,在 Firefox 中,您可以在本地观察更改:
>>> var obj = { foo: 42 }
>>> obj.watch('foo', function() { console.log('changed') })
>>> obj.foo = 69
changed
69
However, this will be soon (late 2017) removed.
但是,这将很快(2017 年末)删除。
回答by BlueRaja - Danny Pflughoeft
There is a library for this: BreakOn()
有一个库: BreakOn()
If you add it to Chrome dev tools as a snippet (sources --> snippets --> right-click --> new --> paste this), you can use it anytime.
如果你把它添加到Chrome浏览器开发工具的一个片段(源- >段- >右键- >新建- >粘贴此),你可以随时使用它。
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:
要使用它,请打开开发工具并运行代码段。然后在myObject.myProperty
更改时中断,从开发控制台调用它:
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.
您还可以将库添加到项目的调试构建中,这样您就无需在breakOn
每次刷新页面时再次调用。
回答by Dima Slivin
This can also be done by using the new Proxyobject 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.
这也可以通过使用新的Proxy对象来完成,其目的正是:拦截对由 Proxy 包装的对象的读取和写入。您只需将要观察的对象包装到代理中,然后使用新包装的对象而不是原始对象。
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.
现在使用wrappedObject,您将在其中提供originalObject,并在中断时检查调用堆栈。
回答by Roland Soós
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;
}
});
}
回答by Alexandros Katechis
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:
决定编写我自己的此解决方案版本,将其保存在 Chrome 的 DevTools 中的一个片段中,并将其包装在一个应该支持 Node 和浏览器的 IIFE 中。还将观察者更改为使用范围变量而不是对象上的属性,这样就不会有名称冲突的可能性,并且任何枚举键的代码都不会“看到”创建的新“私钥”:
(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)
回答by Ivica Puljic
Chrome has this feature built-in in latest versions https://developers.google.com/web/updates/2015/05/view-and-change-your-dom-breakpoints.
Chrome 在最新版本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.
因此不再需要自定义库和解决方案,只需在检查器中右键单击 DOM 元素并选择“中断”->“属性修改”,就是这样。