Firebug for Firefoxには、「プロパティ変更時のブレーク」と呼ばれる素敵な機能があり、任意のオブジェクトのプロパティをマークでき、変更の直前にJavaScriptの実行を停止します。
Google Chromeでも同じことをしようとしていますが、Chromeデバッガーで関数が見つかりません。 Google Chromeでこれを行うにはどうすればよいですか?
ソースをいじくり回しても構わない場合は、アクセサでプロパティを再定義できます。
// 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;
}
});
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):
@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の非標準 console.watch
のため、Object.watch
がすでに存在していることに注意してください。したがって、Firefoxでは、変更をネイティブで監視できます。
>>> var obj = { foo: 42 }
>>> obj.watch('foo', function() { console.log('changed') })
>>> obj.foo = 69
changed
69
ただし、 これはまもなく(2017年後半)削除されます 。
これは、新しい 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);
次に、代わりにoriginalObjectを指定する場所でwrappedObjectを使用し、ブレーク時の呼び出しスタックを調べます。
Chromeには、この機能が最新バージョンに組み込まれています https://developers.google.com/web/updates/2015/05/view-and-change-your-dom-breakpoints 。
したがって、カスタムライブラリとソリューションの必要はありません。インスペクタでDOM要素を右クリックし、[Break on]-> [attribute modification]を選択するだけです。
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とBrowserの両方をサポートする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)