Firefox的Firebug具有一个不错的功能,称为“属性更改中断”,在这里我可以标记任何对象的任何属性,并且它将在更改之前停止JavaScript执行。
我正在尝试在Google Chrome浏览器中实现相同功能,但在Chrome调试器中找不到该功能。如何在Google Chrome浏览器中执行此操作?
Firefox的Firebug具有一个不错的功能,称为“属性更改中断”,在这里我可以标记任何对象的任何属性,并且它将在更改之前停止JavaScript执行。
我正在尝试在Google Chrome浏览器中实现相同功能,但在Chrome调试器中找不到该功能。如何在Google Chrome浏览器中执行此操作?
Answers:
如果您不介意弄乱源代码,则可以使用访问器重新定义属性。
// 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;
}
});
console.watch(obj, 'someProp')
。
window.location
出于安全原因)不起作用。
obj._someProp = obj.someProp;
,似乎与你要归档的内容无关(可能是因为我想念一些东西)
编辑2016.03:Object.observe
在Chrome 50中已弃用并删除
编辑2014.05:Object.observe
已在Chrome 36中添加
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
可以工作。编辑:
请注意console.watch
,由于Firefox的非标准特性,在Firefox中已经存在Object.watch
。因此,在Firefox中,您可以本地监视更改:
>>> var obj = { foo: 42 }
>>> obj.watch('foo', function() { console.log('changed') })
>>> obj.foo = 69
changed
69
但是,将很快(2017年末)将其删除。
oObj[sProp]
,因为getter将进入无限递归。在Chrome中尝试,您将获得RangeError: Maximum call stack size exceeded
。
async
使用此方法的复选框非常金黄: html5rocks.com/en/tutorials/developertools/async-call-stack
async
@cnp所写的复选框,请参阅我的更新
Object.observe
已弃用,不久将被删除:请参阅:chromestatus.com/features/6147094632988672
这也可以通过使用新的Proxy对象来完成,该对象的确切目的是:拦截对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,并检查中断时的调用堆栈。
set
必须返回,true
以确保它不会因跟踪的情况而失败。
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;
}
});
}
决定编写此解决方案的我自己的版本,将其保存在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)
Chrome浏览器具有最新版本https://developers.google.com/web/updates/2015/05/view-and-change-your-dom-breakpoints内置的功能。
因此,不再需要自定义库和解决方案,只需在检查器中右键单击DOM元素,然后选择“中断”->“属性修改”即可。