Firebug for Firefox有一个很好的功能,名为“Break on property change”,我可以在其中标记任何对象的任何属性,它将在更改之前停止JavaScript执行。
我正在尝试在Google Chrome中实现相同功能,但我无法在Chrome调试器中找到该功能。如何在Google Chrome中执行此操作?
答案 0 :(得分:103)
修改2016.03:我已弃用并在Chrome 50中删除Object.observe
<击>
修改2014.05:Chrome 36中添加了Object.observe
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):
@katspaugh建议的console.watch
草图:
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
有效。修改强>
请注意,在Firefox中,由于Firefox的非标准Object.watch
,console.watch
已经存在。因此,在Firefox中,您可以本地监视更改:
>>> var obj = { foo: 42 }
>>> obj.watch('foo', function() { console.log('changed') })
>>> obj.foo = 69
changed
69
答案 1 :(得分:88)
如果您不介意搞乱来源,可以使用访问者重新定义该属性。
// 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 :(得分:66)
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), 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.
答案 3 :(得分:2)
这也可以通过使用新的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,并在break上检查调用堆栈。
答案 4 :(得分:1)
基于 Alexandos Katechis 的出色解决方案,这里是一个不会干扰财产原始价值的代码片段版本。我重命名了它以更好地匹配我在使用它时的想法。
用法:
breakOnChange(anyObject, 'propertyName')
这对于发现诸如 jQuery 之类的全局库被第三方脚本践踏之类的事情非常有帮助。
(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)
答案 5 :(得分: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;
}
});
}
答案 6 :(得分:0)
Chrome在最新版本https://developers.google.com/web/updates/2015/05/view-and-change-your-dom-breakpoints中内置了此功能。
因此不再需要自定义库和解决方案,只需右键单击检查器中的DOM元素,然后选择“中断”即可。 - &GT; &#39;属性修改&#39;那就是它。
答案 7 :(得分:0)
决定编写此解决方案的我自己的版本,将其保存在Chrome的DevTools中的一段代码中,然后将其包装在同时支持Node和Browsers的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)