Точка останова при изменении свойства


Firebug для Firefox имеет приятную функцию, называемую "Break on property change", где я могу отметить любое свойство любого объекта, и он остановит выполнение JavaScript прямо перед изменением.

Я пытаюсь добиться того же в Google Chrome, и я не могу найти функцию в Chrome debugger. Как это сделать в Google Chrome?

6 115

6 ответов:

Если вы не возражаете возиться с источником, вы можете переопределить свойство с помощью метода доступа.

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

чтобы увидеть стек вызовов, вам нужно включить опцию "асинхронный стек вызовов" в инструментах разработки:

chrome async call stack


оригинальный ответ (2012.07):

A 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");

совместимость:

  • In Chrome 20, вы можете вставить его непосредственно в Dev Tools во время выполнения!
  • для полноты: в Firebug 1.10 (Firefox 14) вы должны ввести его на свой сайт (например, через Fiddler, если вы не можете редактировать источник вручную); к сожалению, функции, определенные из Firebug, похоже, не ломаются debugger (или это вопрос конфигурации? пожалуйста, поправьте меня тогда), но console.log строительство.

Edit:

обратите внимание, что в Firefox console.watch уже существует, из-за нестандартного Firefox Object.watch. Следовательно, в Firefox вы можете следить за изменениями изначально:

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

однако, это будет в ближайшее время (в конце 2017 года) удалены.

для этого есть библиотека:BreakOn()

Если вы добавите его в Chrome dev tools в виде фрагмента (источники -- > фрагменты -- > щелкните правой кнопкой мыши -- > создать -- > вставить этой), вы можете использовать его в любое время.


чтобы использовать его, откройте dev-tools и запустите фрагмент кода. Тогда ломать когда myObject.myProperty изменяется, вызовите это из dev-консоли:

breakOn(myObject, 'myProperty');

вы также можете добавить библиотеку в debug-build вашего проекта, чтобы вы не нужно звонить breakOn снова при каждом обновлении страницы.

Это также можно сделать с помощью Прокси объект, целью которого является именно это: перехват чтения и записи в объект, который обернут Прокси. Вы просто обертываете объект, который хотите наблюдать, в прокси-сервер и используете новый обернутый объект вместо исходного.

пример:

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 вместо этого и изучить стек вызовов на перерыв.

Chrome имеет эту функцию встроенную в последних версиях https://developers.google.com/web/updates/2015/05/view-and-change-your-dom-breakpoints.

Так что больше нет необходимости в пользовательских библиотеках и решениях, просто щелкните правой кнопкой мыши на элементе DOM в инспекторе и выберите "Break on" - > "attribute modifications" и все.

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