संपत्ति परिवर्तन पर ब्रेकपॉइंट


147

फ़ायरफ़ॉक्स के लिए फायरबग में एक अच्छी सुविधा है, जिसे "संपत्ति परिवर्तन पर ब्रेक" कहा जाता है, जहां मैं किसी भी वस्तु की किसी भी संपत्ति को चिह्नित कर सकता हूं, और यह परिवर्तन से ठीक पहले जावास्क्रिप्ट निष्पादन को रोक देगा।

मैं Google Chrome में समान प्राप्त करने का प्रयास कर रहा हूं, और मैं Chrome डीबगर में फ़ंक्शन नहीं ढूँढ सकता। मैं इसे Google Chrome में कैसे करूं?


1
यदि आप HTML तत्वों के साथ ऐसा करना चाहते हैं तो stackoverflow.com/a/32686203/308851
chx

जवाबों:


106

यदि आपको स्रोत के साथ खिलवाड़ करने में कोई आपत्ति नहीं है, तो आप एक एक्सेसर के साथ संपत्ति को फिर से परिभाषित कर सकते हैं।

// 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
वहाँ एक प्लग है जिसमें मेरे लिए क्या होगा?
आर्से ज़ाहरे जुले

3
@ अर्सेंज़ाह्रे, दुन्नो हालांकि, आप इसे से एक आसान कार्य कर सकते हैं और उपयोग कर सकते हैं console.watch(obj, 'someProp')
कट्सपॉ

5
यह अंतर्निहित गुणों जैसे window.locationसुरक्षा कारणों से काम नहीं करता है।
qJake

1
DOM तत्वों के लिए बसने वालों के लिए यह पैटर्न थोड़ा संशोधित होना चाहिए। देखें mnaoumov.wordpress.com/2015/11/29/... अधिक जानकारी के लिए
mnaoumov

@katspaugh मैं पूछ सकता हूं कि आपको इसकी आवश्यकता क्यों है obj._someProp = obj.someProp;, यह असंबंधित लगता है कि आप क्या करने की कोशिश कर रहे हैं (शायद इसलिए कि मैं किसी दिन याद कर रहा हूं)
विक्टर

109

संपादित करें 2016.03: Object.observeक्रोम 50 में पदावनत और हटा दिया गया है

2014.05 संपादित करें: Object.observeChrome 36 में जोड़ा गया था

मूल Object.observeकार्यान्वयन वाले क्रोम 36 जहाज जिनका लाभ यहां लिया जा सकता है:

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

कॉल स्टैक देखने के लिए, आपको देव टूल में "async कॉल स्टैक" विकल्प को सक्षम करने की आवश्यकता है:

क्रोम async कॉल स्टैक


मूल उत्तर (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 में पेस्ट कर सकते हैं!
  • पूर्णता के लिए: फायरबग 1.10 (फ़ायरफ़ॉक्स 14) में, आपको इसे अपनी वेबसाइट में इंजेक्ट करना होगा (जैसे कि फ़िडलर के माध्यम से यदि आप स्रोत को मैन्युअल रूप से संपादित नहीं कर सकते हैं); दुख की बात है कि फायरबग से परिभाषित कार्य टूटने नहीं लगते हैं debugger(या यह विन्यास की बात है? कृपया मुझे ठीक करें), लेकिन console.logकाम करता है।

संपादित करें:

ध्यान दें कि console.watchफ़ायरफ़ॉक्स के गैर-मानक के कारण फ़ायरफ़ॉक्स में पहले से मौजूद है Object.watch। इसलिए फ़ायरफ़ॉक्स में, आप मूल रूप से परिवर्तनों के लिए देख सकते हैं:

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

हालांकि, इसे जल्द (2017 के अंत में) हटा दिया जाएगा


1
वैसे, यह लगता है कि कस्टम कोड में डिबगर को हिट करने में असमर्थ हो रहा है
फायरबग

1
@ColeReed हमें गेटर में इसे पुनः प्राप्त करने के लिए कहीं न कहीं मूल्य संग्रह करना चाहिए; इसे संग्रहित नहीं किया जा सकता है oObj[sProp], क्योंकि गेट्टर एक अनंत पुनरावृत्ति में प्रवेश करेगा। इसे क्रोम में आज़माएं, आपको मिलेगा RangeError: Maximum call stack size exceeded
jakub.g

1
मैं इसे जोड़ना चाहता हूं, क्योंकि asyncइस दृष्टिकोण के साथ चेकबॉक्स इतना सुनहरा है: html5rocks.com/en/tutorials/developertools/async-call-stack
cnp

1
@PhiLho को स्टैक देखना संभव है, asyncचेकबॉक्स के साथ @cnp ने लिखा, मेरा अपडेट देखें
jakub.g

1
इस उत्तर को अद्यतन करना चाहिए: Object.observeपदावनत किया गया है और जल्द ही हटा दिया जाएगा: देखें: chromestatus.com/features/6147094632988672
अमीर गन्नें

79

इसके लिए एक पुस्तकालय है: ब्रेकऑन ()

यदि आप इसे स्निपेट (स्रोतों -> स्निपेट -> राइट-क्लिक -> नया -> पेस्ट करें ) के रूप में क्रोम देव टूल्स में जोड़ते हैं , तो आप इसे कभी भी उपयोग कर सकते हैं।


इसका उपयोग करने के लिए, देव-उपकरण खोलें और स्निपेट चलाएं। फिर जब myObject.myPropertyपरिवर्तित हो जाए तो उसे तोड़ने के लिए देव-कंसोल से कॉल करें:

breakOn(myObject, 'myProperty');

आप अपने प्रोजेक्ट के डिबग-बिल्ड में लाइब्रेरी भी जोड़ सकते हैं ताकि आपको breakOnपेज को रीफ्रेश करने के लिए हर बार फिर से कॉल करने की आवश्यकता न पड़े।


5

यह नई प्रॉक्सी ऑब्जेक्ट का उपयोग करके भी किया जा सकता है जिसका उद्देश्य बिल्कुल यही है: रीड्स को इंटरसेप्ट करना और उस ऑब्जेक्ट को लिखता है जो प्रॉक्सी द्वारा लिपटा हुआ है। आप बस उस वस्तु को लपेटते हैं जिसे आप प्रॉक्सी में निरीक्षण करना चाहते हैं और अपने मूल के बजाय नए लिपटे ऑब्जेक्ट का उपयोग करते हैं।

उदाहरण:

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

अब रैपऑबजेक्ट का उपयोग करें जहां आप ऑरिजनल ऑबजेक्ट की आपूर्ति करेंगे और ब्रेक पर कॉल स्टैक की जांच करेंगे।


ट्रैक किए गए मामलों के अलावा अन्य के लिए विफल होने के लिए प्रॉक्सी की setवापसी होनी चाहिए true
कियुकिन

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

इस समाधान के अपने स्वयं के संस्करण को लिखने का फैसला किया, इसे क्रोम के DevTools में एक स्निपेट में सहेजें, और इसे 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)

-2

Chrome में यह सुविधा बिल्ट-इन नवीनतम संस्करणों https://developers.google.com/web/updates/2015/05/view-and-change-your-dom-breakpoints है

तो कस्टम पुस्तकालयों और समाधानों के लिए और कोई ज़रूरत नहीं है, बस इंस्पेक्टर में DOM तत्व पर क्लिक करें और 'ब्रेक ऑन' -> 'एट्रिब्यूट संशोधनों' का चयन करें और यही वह है।


10
उन्होंने (जेएस वस्तु) संपत्ति में बदलाव के लिए कहा, न कि डोम विशेषता मूल्य परिवर्तन
जेड। खुल्ला

1
@ इविका यह एक अच्छी तकनीक है, लेकिन इसे लगाने की गलत जगह है। यह एक टिप्पणी के रूप में ठीक होगा, लेकिन उत्तर के रूप में नहीं।
bnieland
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.