재산 변경에 대한 중단 점


147

Firefox 용 Firebug에는 "속성 변경시 중단"이라는 멋진 기능이 있는데, 여기서 객체의 모든 속성을 표시 할 수 있으며 변경 직전에 JavaScript 실행이 중지됩니다.

Chrome에서 동일한 결과를 얻으려고하는데 Chrome 디버거에서 기능을 찾을 수 없습니다. 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
나를 위해 그것을 할 수있는 플러그가 있습니까?
Arsen Zahray

3
@ArsenZahray, 던노. 그러나 유용한 기능을 만들어서처럼 사용할 수 console.watch(obj, 'someProp')있습니다.
katspaugh

5
window.location보안상의 이유로 내장 속성에 대해서는 작동하지 않습니다 .
qJake

1
DOM 요소의 setter를 디버그하려면이 패턴을 약간 수정해야합니다. 자세한 내용은 mnaoumov.wordpress.com/2015/11/29/… 을 참조하십시오.
mnaoumov

@ katspaugh 내가 왜 필요한지 물어볼 수 있습니다 obj._someProp = obj.someProp;, 그것은 당신이 보관하려고하는 것과 관련이없는 것 같습니다 (아마도 내가 누락되어 있기 때문에)
Victor

109

2016.03 수정 : Object.observeChrome 50에서 더 이상 사용되지 않고 제거되었습니다.

2014.05 수정 : Object.observeChrome 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) :

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에서는 런타임에 개발자 도구에 직접 붙여 넣을 수 있습니다!
  • 완벽 함 : Firebug 1.10 (Firefox 14)에서는 웹 사이트에 소스를 삽입해야합니다 (예 : 소스를 수동으로 편집 할 수없는 경우 Fiddler를 통해). 슬프게도 Firebug에서 정의 된 기능은 깨지지 않는 것 같습니다 debugger(또는 구성의 문제입니까? 그런 다음 나를 수정하십시오) console.log.

편집하다:

console.watchFirefox의 비표준으로 인해 Firefox에는 이미 존재합니다 Object.watch. 따라서 Firefox에서는 기본적으로 변경 사항을 감시 할 수 있습니다.

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

그러나 이것은 곧 (2017 년 말) 제거 될 것 입니다.


1
그런데, 방화범이 끌려 1.8과 1.9 사이의 회귀 사용자 지정 코드에 디버거를 공격 할 수없는 것으로 보인다 문제 5757 ->의 중복 문제 5221
jakub.g

1
@ColeReed getter에서 값을 검색하려면 어딘가에 값을 저장해야합니다. oObj[sProp]getter가 무한 재귀를 입력하기 때문에에 저장할 수 없습니다 . Chrome에서 사용해보십시오 RangeError: Maximum call stack size exceeded.
jakub.g

1
I "는,이를 추가하고 싶습니다 async: 확인란이 방법 너무 황금이다 html5rocks.com/en/tutorials/developertools/async-call-stack
CNP

1
@PhiLho 그것은 async@cnp이 쓴 체크 박스 와 함께 스택을 볼 수 있습니다 , 내 업데이트를 참조하십시오
jakub.g

1
이 답변으로 업데이트해야합니다 : Object.observe사용되지 않습니다를 곧 제거 될 것입니다 : 참조 : chromestatus.com/features/6147094632988672
아미르 Gonnen

79

이를위한 라이브러리가 있습니다 : BreakOn ()

당신이 조각으로 크롬 개발 도구에 추가하는 경우 (소스 -> 미리보기 -> 오른쪽 클릭 -> 새로 만들기 -> 붙여 넣기 ) , 당신은 언제든지 사용할 수 있습니다.


사용하려면 dev-tools를 열고 스 니펫을 실행하십시오. 그런 다음 myObject.myProperty변경 되었을 때 중단 하려면 dev-console에서 다음을 호출하십시오.

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

이제 대신 originalObject를 제공 할 위치에 wrappedObject를 사용하고 중단시 호출 스택을 검사하십시오.


추적 된 경우를 제외하고 프록시 가 실패하지 않도록 프록시 set를 반환해야합니다 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

이 솔루션의 자체 버전을 작성하기로 결정하고 Chrome의 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 요소를 마우스 오른쪽 버튼으로 클릭하고 'Break on'-> 'attribute modified'를 선택하십시오.


10
그는 DOM 속성 값 변경이 아닌 (js 객체) 속성 변경을 요청했습니다
Z. Khullah

1
@Ivica 이것은 좋은 기술이지만, 이것을 넣는 것은 잘못된 곳입니다. 의견으로는 좋지만 답변으로는 좋지 않습니다.
bnieland
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.