javascript

이벤트 버블링, 캡쳐링, 위임 / 자바스크립트 this

인재재 2024. 6. 10. 20:04

앞서 이벤트 등록이란?

이벤트 등록은 웹 에서 사용자의 입력을 받기 위해 필요합니다. 자세하게 말하자면  웹 개발자들이 화면에 동적인 기능을 추가하여, 사용자의 입력에 따라 추가 동작을 구현할 수 있게 해주는데 이벤트의 예시로는 마우스 클릭, 움직이기, 키보드 누르기 등이 있습니다. 여기서 브라우자가 이벤트를 감지하는 방식에 관하여 아래에 자세히 얘기해보도록 하겠습니다.

1. 이벤트 버블링 - Event Bubbling

이벤트는 개발자가 추가한 요소 뿐 아니라 다른 요소에도 전파가 되는 특성을 가지고 있는데,
이벤트 버블링(Event Bubbling)이란 어떤 요소에서 이벤트가 발생할 때 해당 요소에 등록된 이벤트가 동작하는 것뿐 아니라 해당 이벤트가  부모 요소 (상위요소)로 이벤트가 전달되어 가는 특성을 말합니다.

브라우저는 특정 화면 요소에서 이벤트가 발생했을 때 그 이벤트를 최상위에 있는 화면 요소까지 이벤트를 전파시키는데 

단, 이벤트가 등록되어 있는 요소로만 전달이 됩니다. 

" 이벤트 버블링은 이벤트 객체의 stopPropagation 메소드로 전파를 막을 수 있습니다! "

2. 이벤트 캡쳐링 - Event Capturing

이벤트 캡처링(Event Capturing)은 이벤트 버블링과는 진행되는 방향이 반대인 이벤트 전파 방식입니다.


표준 DOM 이벤트흐름 단계로 아래 그림과 같이 캡처링 단계 -> 타깃 단계 (타깃에 등록된 이벤트핸들러 동작) -> 버블링 단계 의 과정을 통해 이벤트 핸들러가 호출되는데 캡처링 단계 자체가 매우 드문 경우입니다. 

아래 그림으로 캡처링과 버블링의 차이를 한 눈에 볼 수 있습니다. 켑처링은 특정 이벤트가 발생했을 때 최상위 요소에서 해당 태그를 찾아 내려갑니다.

 

" 캡처링 단계에서 이벤트 핸들러를 동작시키려면 addEventListener 세번째 프로퍼티나 capture에 true값을 주면 됩니다! "

 elem.addEventListener("click", e => alert(`캡쳐링 단계: ${elem.tagName}`), true);
        elem.addEventListener("click", e => alert(`버블링 단계: ${elem.tagName}`));

이벤트 캡쳐링과 이벤트 버블링의 차이

3. 이벤트 위임 - Event Delegation

버블링 개념을 활용하여 효과적인 이벤트 관리를 할 수 있는데,

 

예시로 input(요소)에 이벤트를 달아주고 새로운 input을 만들 면 새로운 요소는 이벤트 적용이 되어있지않기에 번거롭게 또 이벤트 리스너를 달아줘야할 때인데 이것을 해결할 수 있는 방법이 바로 이벤트 위임(Event Delegation)입니다.

input(요소)에 이벤트를 달아주는 것이 아닌 그 보다 부모 요소 (상위 요소)에 이벤트 리스너를 달아놓고 하위에서 발생한 클릭 이벤트를 감지하는 것입니다.

 

정리하자면 자식 요소 각각에 이벤트 핸들러를 하나씩 등록할 필요 없이 부모 요소에서 한 번에 자식 요소들에 발생한 이벤트를 관리하는 것인데요. 이렇게 이벤트를 다루는 방식을 자식 요소의 이벤트를 부모 요소에 위임한다고 해서 이벤트 위임(Event Delegation)이라고 부르고, 이 부분에서 이벤트 버블링이 활용되는 것입니다.

자바스크립트 this란?

자바스크립트에는 this키워드는 개체를 나타냅니다. 즉 '누가 나를 불렀느냐' 라고 생각하면 직관적일 것 같습니다.

 

함수 호출 방식에 의해 this에 바인딩할 어떤 객체가 동적으로 결정됩니다.

함수를 선언할 때정적으로 결정되는 것이 아니고, 함수를 호출할 때 함수가 어떻게 호출되었는지에 따라 this에 바인딩할 객체가 동적으로 결정됩니다.

 

웹 브라우저에서 this가 사용될 때는 전역 객체, Window 객체를 가지게 됩니다. 하지만 객체의 메소드를 정의하기 위한 함수 안에선 메소드를 호출한 객체를 가리키게 됩니다.

호출 방식에 따라 짧게 정리 해보도록 하겠습니다

 

함수 호출

기본적으로 this는 전역객체에 바인딩 됩니다. 

  console.log("this is : ",  this);

 

 

메소드 호출

메소드 내부의 this는 해당 메소드를 소유한 객체, 즉 해당 메소드를 호출한 객체에 바인딩 됩니다.

var obj1 = {
  name: 'A',
  sayName: function() {
    console.log(this.name);
  }
}

var obj2 = {
  name: 'B'
}

obj2.sayName = obj1.sayName;

obj1.sayName(); // A
obj2.sayName(); // B