2012-07-23 34 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; 
    } 
    }); 
}