Özellik değişikliğinde kesme noktası


153

Firebug for Firefox, herhangi bir nesnenin herhangi bir özelliğini işaretleyebileceğim "Özellik değişikliğinde kırılma" adlı güzel bir özelliğe sahiptir ve değişiklikten hemen önce JavaScript'in çalışmasını durdurur.

Aynı şeyi Google Chrome'da elde etmeye çalışıyorum ve işlevi Chrome hata ayıklayıcıda bulamıyorum. Bunu Google Chrome'da nasıl yaparım?


1
Bunu HTML öğeleriyle yapmak istiyorsanız stackoverflow.com/a/32686203/308851
chx

Yanıtlar:


112

Kaynakla uğraşmaktan çekinmiyorsanız, özelliği bir erişimci ile yeniden tanımlayabilirsiniz.

// 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
bunu benim için yapacak bir fiş var mı?
Arsen Zahray

3
@ArsenZahray, dunno. Ancak, ondan kullanışlı bir işlev yapabilir ve benzeri kullanabilirsiniz console.watch(obj, 'someProp').
katspaugh

5
Bu, window.locationgüvenlik nedenleriyle olduğu gibi yerleşik özellikler için çalışmaz .
qJake

1
DOM öğeleri için ayarlayıcılarda hata ayıklamak için bu şablon biraz değiştirilmelidir. Daha fazla ayrıntı için mnaoumov.wordpress.com/2015/11/29/… bakın
mnaoumov

@katspaugh neden buna ihtiyacın olduğunu sorabilir obj._someProp = obj.someProp;miyim, arşivlemeye çalıştığın şeyle ilgisiz görünüyor (muhtemelen bir şeyler kaçırdığım için)
Victor

109

2016.03 Düzenleme: Object.observekullanımdan kaldırıldı ve Chrome 50'de kaldırıldı

2014.05 Düzenleme: Object.observeChrome 36'ya eklendi

Chrome 36 Object.observe, buradan yararlanılabilecek yerel uygulamayla birlikte gelir:

myObj = {a: 1, b: 2};
Object.observe(myObj, function (changes){
    console.log("Changes:");
    console.log(changes);
    debugger;
})
myObj.a = 42;

Yalnızca geçici olarak istiyorsanız, geri aramayı bir değişkene kaydetmeli ve Object.unobserveişiniz bittiğinde çağırmalısınız :

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

Kullanırken Object.observe, ödev hiçbir şeyi değiştirmediğinde, örneğin yazdıysanız, bilgilendirilmeyeceğinizi unutmayın myObj.a = 1.

Çağrı yığınını görmek için Geliştirme Araçlarında "eşzamansız çağrı yığını" seçeneğini etkinleştirmeniz gerekir:

chrome async call stack


Orijinal cevap (2012.07):

console.watch@Katspaugh'un önerdiği bir taslak:

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

Çağrı:

console.watch(obj, "someProp");

Uyumluluk:

  • Chrome 20'de, bunu çalışma zamanında doğrudan Geliştirme Araçlarına yapıştırabilirsiniz!
  • Tamlık için: Firebug 1.10'da (Firefox 14), web sitenize enjekte etmeniz gerekir (örneğin, kaynağı manuel olarak düzenleyemiyorsanız Fiddler aracılığıyla); ne yazık ki, Firebug'dan tanımlanan işlevler çalışmıyor gibi görünüyor debugger(yoksa bir yapılandırma sorunu mu? Lütfen o zaman beni düzeltin), ama console.logçalışıyor.

Düzenle:

Firefox'un console.watchstandart olmaması nedeniyle Firefox'ta zaten mevcut olduğunu unutmayın Object.watch. Dolayısıyla, Firefox'ta değişiklikleri yerel olarak izleyebilirsiniz:

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

Ancak, bu yakında (2017'nin sonunda) kaldırılacaktır .


1
Bu arada, özel kodda hata ayıklayıcıya
ulaşamamak

1
@ColeReed, değeri alıcıda geri almak için bir yerde saklamalıyız; oObj[sProp]alıcı sonsuz özyinelemeye gireceği için depolanamaz . Chrome'da deneyin, alacaksınız RangeError: Maximum call stack size exceeded.
jakub.g

1
asyncBu yaklaşımla onay kutusu çok altın olduğundan bunu eklemek istiyorum : html5rocks.com/en/tutorials/developertools/async-call-stack
cnp

1
@PhiLho, async@cnp'nin yazdığı onay kutusu ile yığını görmek mümkün , güncellememe bakın
jakub.g

1
Bu yanıtı güncellemelisiniz: Object.observekullanımdan kaldırıldı ve yakında kaldırılacak: bkz: chromestatus.com/features/6147094632988672
Amir Gonnen

83

Bunun için bir kütüphane var: BreakOn ()

Eğer bir pasajı olarak Krom dev araçları eklerseniz (kaynaklar -> parçacıkları -> sağ tıklayın -> Yeni -> yapıştırmak bu ) , istediğiniz zaman kullanabilirsiniz.


Kullanmak için dev-tools'u açın ve snippet'i çalıştırın. Sonra değiştirildiğinde kırmak myObject.myPropertyiçin bunu dev-konsolundan çağırın:

breakOn(myObject, 'myProperty');

Kitaplığı projenizin hata ayıklama yapısına da ekleyebilirsiniz, böylece breakOnsayfayı her yenilediğinizde tekrar aramanıza gerek kalmaz .


Geliştirici konsolundan hata ayıklamaya çalışan herkes için en iyi çözüm. Herhangi bir web sitesinde yeniden kullanmak için fazladan çaba yok, harika!
Chris Hayes

5

Bu aynı zamanda amacı tam olarak şu olan yeni Proxy nesnesi kullanılarak da yapılabilir : Okumaları ve Proxy tarafından sarılmış nesneye yazılanları yakalamak. Sadece gözlemlemek istediğiniz nesneyi bir Proxy'ye sarın ve orijinaliniz yerine yeni sarılmış nesneyi kullanın.

Misal:

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

Şimdi bunun yerine originalObject sağlayacağınız ve arama yığınını kesintiye uğrattığınız yerde wrappedObject kullanın.


Proxy'ler , takip edilen durumlar dışında başarısız olmamak için setgeri dönmelidir true.
keaukraine

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

1

Bu çözümün kendi versiyonunu yazmaya karar verdim, onu Chrome DevTools'ta bir parçacığa kaydetti ve onu hem Düğüm hem de Tarayıcıları desteklemesi gereken bir IIFE'ye sardım. Ayrıca, gözlemciyi, nesne üzerinde bir özellik yerine bir kapsam değişkeni kullanacak şekilde değiştirildi, öyle ki ad çatışmaları olasılığı yok ve anahtarları numaralandıran herhangi bir kod, oluşturulan yeni "özel anahtarı" "görmeyecek":

(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)

-3

Chrome, bu özelliğe en son sürümlerde yerleşik olarak sahiptir: https://developers.google.com/web/updates/2015/05/view-and-change-your-dom-breakpoints .

Artık özel kitaplıklara ve çözümlere gerek yok, denetçideki DOM öğesine sağ tıklayın ve "Ara" -> "öznitelik değişiklikleri" ni seçin, hepsi bu.


10
DOM özellik değeri değişikliğini değil (js nesnesi) özellik değişikliğini istedi
Bernardo Dal Corno

1
@Ivica Bu iyi bir teknik, ama bunu koymak için yanlış yer burası. Yorum olarak iyi olurdu, ama cevap olarak değil.
bnieland
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.