Firebug for Firefox 有一个很好的功能,称为“中断属性更改”,我可以在其中标记任何对象的任何属性,并且它会在更改之前立即停止 JavaScript 执行。
我正在尝试在 Google Chrome 中实现相同的功能,但在 Chrome 调试器中找不到该功能。如何在 Google Chrome 中执行此操作?
Firebug for Firefox 有一个很好的功能,称为“中断属性更改”,我可以在其中标记任何对象的任何属性,并且它会在更改之前立即停止 JavaScript 执行。
我正在尝试在 Google Chrome 中实现相同的功能,但在 Chrome 调试器中找不到该功能。如何在 Google Chrome 中执行此操作?
如果您不介意弄乱源代码,则可以使用访问器重新定义该属性。
// 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;
}
});
编辑 2016.03:Object.observe
在 Chrome 50 中已弃用并删除
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
.
要查看调用堆栈,您需要在开发工具中启用“异步调用堆栈”选项:
原答案(2012.07):
一个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;
}
});
}
调用:
console.watch(obj, "someProp");
兼容性:
debugger
(或者是配置问题?然后请纠正我),但console.log
有效。>>> var obj = { foo: 42 }
>>> obj.watch('foo', function() { console.log('changed') })
>>> obj.foo = 69
changed
69
编辑:Object.watch
已在 Firefox 57 中删除。
这也可以通过使用新的Proxy对象来完成,其目的正是:拦截对由 Proxy 包装的对象的读取和写入。您只需将要观察的对象包装到代理中,然后使用新包装的对象而不是原始对象。
例子:
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);
现在使用wrappedObject,您将在其中提供originalObject,并在中断时检查调用堆栈。
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;
}
});
}