财产变化的断点

Ars*_*ray 139 javascript debugging firefox firebug google-chrome

Firebug for Firefox有一个很好的功能,名为"Break on property change",我可以在其中标记任何对象的任何属性,它将在更改之前停止JavaScript执行.

我正在尝试在Google Chrome中实现相同功能,但我无法在Chrome调试器中找到该功能.如何在Google Chrome中执行此操作?

jak*_*b.g 104

编辑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;
Run Code Online (Sandbox Code Playgroud)

如果您只想暂时使用它,则应将回调存储在变量中并Object.unobserve在完成后调用:

myObj = {a: 1, b: 2};
func = function() {debugger;}
Object.observe(myObj, func);
myObj.a = 42;
Object.unobserve(myObj, func);
myObj.a = 84;
Run Code Online (Sandbox Code Playgroud)

请注意,在使用时Object.observe,如果作业没有改变任何内容,您将不会收到通知,例如,如果您已经写过myObj.a = 1.

要查看调用堆栈,您需要在Dev Tools中启用"异步调用堆栈"选项:

chrome异步调用堆栈


原始答案(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;
       }
   });
}
Run Code Online (Sandbox Code Playgroud)

调用:

console.watch(obj, "someProp");
Run Code Online (Sandbox Code Playgroud)

兼容性:

  • 在Chrome 20中,您可以在运行时将其直接粘贴到Dev Tools中!
  • 为了完整性:在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
Run Code Online (Sandbox Code Playgroud)

但是,这将很快(2017年底)删除.


kat*_*ugh 97

如果您不介意搞乱来源,可以使用访问者重新定义该属性.

// 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;
    }
});
Run Code Online (Sandbox Code Playgroud)

  • 出于安全原因,这不适用于内置属性,例如`window.location`. (4认同)
  • @ArsenZahray,不知道.但是,你可以用它来制作一个方便的函数,并使用像`console.watch(obj,'someProp')`. (3认同)
  • 有插件可以帮我吗? (2认同)

Blu*_*eft 72

有一个库: BreakOn()

如果您将其作为代码段添加到Chrome开发工具(来源 - >代码段 - >右键单击 - >新建 - >粘贴此内容),您可以随时使用它.


要使用它,请打开开发工具并运行代码段.然后在myObject.myProperty更改时中断,从dev-console调用它:

breakOn(myObject, 'myProperty');
Run Code Online (Sandbox Code Playgroud)

您还可以将库添加到项目的debug-build中,这样breakOn每次刷新页面时都不需要再次调用.

  • 不适用于像bool这样的全局窗口变量 (2认同)

Dmi*_* S. 6

这也可以通过使用新的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);
Run Code Online (Sandbox Code Playgroud)

现在使用wrappedObject,您将在其中提供originalObject,并在中断时检查调用堆栈。


Rol*_*oós 5

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;
    }
  });
}
Run Code Online (Sandbox Code Playgroud)