Точка останова при изменении свойства
Firebug для Firefox имеет замечательную функцию, называемую "Break on change property", где я могу пометить любое свойство любого объекта, и он остановит выполнение JavaScript прямо перед изменением.
Я пытаюсь добиться того же в Google Chrome, и я не могу найти функцию в отладчике Chrome. Как мне это сделать в Google Chrome?
Ответы
Ответ 1
Если вы не против возиться с источником, вы можете переопределить свойство с помощью аксессора.
// 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
Изменить 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
.
Чтобы увидеть стек вызовов, вам нужно включить опцию "асинхронный стек вызовов" в Dev Tools:
![chrome async call stack]()
Оригинальный ответ (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");
Совместимость:
- В Chrome 20 вы можете вставить его прямо в Dev Tools во время выполнения!
- Для полноты: в Firebug 1.10 (Firefox 14) вы должны добавить его на свой веб-сайт (например, через Fiddler, если вы не можете редактировать источник вручную); к сожалению, функции, определенные из Firebug, похоже, не работают на
debugger
(или это вопрос конфигурации? пожалуйста, исправьте меня тогда), но console.log
работает.
Редактировать:
Обратите внимание, что в Firefox console.watch
уже существует из-за нестандартного Object.watch
. Следовательно, в Firefox вы можете наблюдать за изменениями:
>>> var obj = { foo: 42 }
>>> obj.watch('foo', function() { console.log('changed') })
>>> obj.foo = 69
changed
69
Однако, это будет скоро (конец 2017) удалено.
Ответ 3
Для этого есть библиотека: BreakOn()
Если вы добавите его в инструменты Chrome dev как фрагмент (источники → фрагменты → щелкните правой кнопкой мыши → новый → вставить этот), вы можете использовать его в любое время.
Чтобы использовать его, откройте инструменты dev и запустите фрагмент. Затем для разрыва при изменении myObject.myProperty
вызовите это из dev-console:
breakOn(myObject, 'myProperty');
Вы также можете добавить библиотеку в проект debug-build, поэтому вам не нужно снова звонить breakOn
при каждом обновлении страницы.
Ответ 4
Это также можно сделать, используя новый объект 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 вместо этого и исследуете стек вызовов при разрыве.
Ответ 5
Chrome имеет эту функцию, встроенную в последние версии https://developers.google.com/web/updates/2015/05/view-and-change-your-dom-breakpoints.
Поэтому больше нет необходимости в пользовательских библиотеках и решениях, просто щелкните правой кнопкой мыши на элементе DOM в инспекторе и выберите "Разбить" → "Изменение атрибутов" и все.
Ответ 6
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;
}
});
}
Ответ 7
Решил написать свою версию этого решения, сохранить ее в виде фрагмента в Chrome DevTools и обернуть в IIFE, который должен поддерживать как Node, так и Browser. Также изменил наблюдатель, чтобы использовать переменную области видимости, а не свойство объекта, чтобы исключить возможность конфликта имен, и любой код, который перечисляет ключи, не будет "видеть" новый "закрытый ключ", который создается:
(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)