2012-07-23 36 views
102

Firebug for firefox有一个很好的功能,叫做“Break on property change”,我可以标记任何对象的任何属性,并且它会在更改之前停止javascript执行。如何在Chrome中“破解属性更改”?

我想在谷歌浏览器中实现相同的功能,并且我无法在Chrome调试器中找到该功能。我如何在谷歌浏览器中执行此操作?

+1

如果你想与HTML元素做到这一点看http://stackoverflow.com/a/32686203/308851 – chx 2015-09-21 02:09:08

回答

65

如果你不介意弄乱源头,你可以使用访问者重新定义属性。

// 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

是有一个插件,其中会为我做的? – 2012-07-23 18:46:56

+3

@ArsenZahray,dunno。然而,你可以使用一个方便的函数,像'console.watch(obj,'someProp')'一样使用。 – katspaugh 2012-07-23 18:54:46

+2

出于安全原因,这对于诸如'window.location'之类的内置属性不起作用。 – qJake 2014-10-07 19:26:01

94

编辑2016.03:Object.observe被弃用,除去铬50

编辑2014.05:Object.observe在铬加入36个

铬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

要查看调用堆栈,您需要启用 “异步调用堆栈” 选项,在开发工具:

chrome async call stack


原来的答复(2012.07):

A console.watch草图如@katspaugh所示:

console = console || {}; // just in case 
console.watch = function(oObj, sProp) { 
    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"); 

兼容性:

  • 在Chrome中20,你可以直接在开发工具在运行时将其粘贴!
  • 为了完整性:在Firebug 1.10(Firefox 14)中,您必须将其注入您的网站(例如,如果您无法手动编辑源代码,则通过Fiddler注入);不幸的是,从Firebug定义的函数似乎没有在debugger(或者它是一个配置问题?请纠正我然后),但console.log工程。

编辑:

注意,在Firefox,console.watch已经存在,由于Firefox的非标准Object.watch。因此,在Firefox中,您可以本机观察更改:

>>> var obj = { foo: 42 } 
>>> obj.watch('foo', function() { console.log('changed') }) 
>>> obj.foo = 69 
changed 
69 

但是,this will be soon (late 2017) removed

+0

谢谢,非常漂亮! – katspaugh 2012-07-26 06:56:15

+1

顺便说一句,似乎是不能打在自定义代码的调试器Firebug的1.8和1.9之间的回归:5757问题(http://code.google.com/p/fbug/issues/detail?id=5757 ) - > [issue 5221](http://code.google.com/p/fbug/issues/detail?id=5221) – 2012-07-26 09:22:27

+0

的重复这非常有帮助! – Wint 2013-04-19 01:02:33

46

有这个库:BreakOn()

如果你把它添加到Chrome浏览器开发工具的一个片段(来源 - >段 - >右键 - >新建 - >粘贴this,你可以随时使用它。


要使用它,请打开开发工具并运行代码段。当myObject.myProperty被改变,那么打破,各个DEV-控制台称之为:

breakOn(myObject, 'myProperty'); 

您还可以将库添加到您的项目的调试,编译,所以你不需要每次刷新的时间再打电话breakOn页。

+2

太棒了!适用于Google Chrome 52.0.2743.116。 – 2016-09-17 06:26:55

+2

太棒了!我很惊讶,它甚至可以使用Chrome 56的breakOn(myElement.style,'transform')'。 – 2017-07-17 18:06:28

+1

在Chrome 60.0.3112.90上使用breakOn(myInputElement,'value')。 – 2017-08-11 11:23:21

0

这也可以通过使用新的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和审查破调用堆栈。

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; 
    } 
    }); 
}