• 카테고리

    질문 & 답변
  • 세부 분야

    풀스택

  • 해결 여부

    해결됨

이벤트 리스너에서의 this에 대해 여쭙고 싶습니다

22.03.10 15:51 작성 조회수 365

0

강사님 안녕하세요

1. 7분에서
button.addEventListener('click', function(){

concole.log(this.textContext);

});

에서의 this에 대해 질문드리고 싶습니다

이때 this가 햇갈린 이유는 다음과 같습니다

2. 지난번에 드렸던 질문의 소스코드에서

var relationship1 = {
    name:'zero',
    friends : ['nero', 'hero', 'xero'],
    logFriends: function(){
        var that = this;
         console.log(`this: ${this}, that: ${that}`);
        this.friends.forEach(function(friend){
            console.log(that.name,friend);
            console.log(`this: ${this}, that: ${that}`);
        });
    }
}
relationship1.logFriends();
 
 
여기서 forEach 함수 내에 있는 콜백함수
funtion( ) 의 this는
호출되는 시점에
객체.function(friend){
            console.log(that.name,friend);
            console.log(`this: ${this}, that: ${that}`);
      }
 
형식이 아닌
foreach( ) 호출 후에
 
콜백함수인 function( )이 단일로 호출이 되었기에
 
this가 window 라는 것을 이해했습니다
 
 
 
 
강의 7분 이벤트리스너에서의 this의 예시에서도

button.addEventListener('click', function(){

concole.log(this.textContext);

});

에서

button.function() 형식이 아닌

button.addEventListener( )가 호출된 다음

콜백함수로 function( ) 자체로만 호출이 되는건데

function( ) 안의 this가 window 가 아닌, button 을 가리키는 이유가 이해가 어려워서 질문드리고 싶습니다

 

답변 1

답변을 작성해보세요.

1

해당 함수 선언이 콜백 함수 역할이라는 데 주목하셔야 합니다.

forEach의 function의 this나 addEventListener의 function의 this는 각각 forEach나 addEventListener에 의해 조작될 수 있습니다.

button.addEventListener는 콜백 함수 function의 this를 조작한 겁니다. 아래 코드와 같이요.

button = {
  addEventListener(eventName, cb) {
    cb.call(this);
  }
}

button.addEventListener의 this는 button인데 call로 콜백함수 cb의 this를 button으로 바꿀 수 있습니다.

forEach는 콜백함수의 this를 조작하지 않은 겁니다.

강사님 답변해주셔서 감사합니다

아직 이해가 어려운 부분이 있어서 더 질문드리고 싶습니다

질문1.
라이브러리에 선언된
button 객체의 원형이
button = {
  addEventListener(eventName, cb) {
    cb.call(this);
  }
}

라는 말씀으로 이해해도 될까요?


질문2. 
제가 봤을 때는
소스코드가 실행이 될 때
콜백 함수 function( ) 호출 시점에서
function( )단일로 호출되므로 
아무리 생각해도, 안의 this가 window 같습니다

조작을 했다는 말씀이
소스코드가
실행이 될 때 V8 엔진이

이벤트리스너 소스코드

button.addEventListener('click', function(){ });


실행 도중에 
button = {
  addEventListener(eventName, cb) {
    cb.call(this);
  }
}
button.addEventListener.cb.call(this);

이런 식으로 중간에 조작해서 실행했다는 말씀이신가요?


질문3.
현재 제 수준에서는 이해가 어려워서 혹시 call 함수를 공부하면 이해하는 데 도움이 되는지도 질문드리고 싶습니다


1. 그냥 예시를 든 것입니다. C++로 작성되어있을거라서 구체적인 코드는 모릅니다.

2. 단순히 호출 시에 function에 다른 this를 바인딩한 것입니다.

function은 기본적으로 this가 window라고 했죠? 그리고 이 this는 정확하게는 호출 시에 정해집니다. function의 이름이 a라고 했을 때 a();를 하면 this가 window가 되는 것이고, button.a()를 하면 this가 button이 되는겁니다. addEventListener에 넣은 function은 호출 시에 내부적으로 function.call(태그)를 해서 this를 태그로 바꾸는 것이고요.

강사님 너무 많은 질문을 받아주셔서 감사합니다

그러면 이 조작이라는 것을 이렇게 이해해도 되는지 질문드리고 싶습니다
1.
V8 엔진이 소스코드를 실행 중에
2.
이벤트 리스너 함수를 만나면
3.
이벤트 리스너 함수를
엔진 내부에 C++ 로 미리 정의되어 있는 소스코드로 조작을 해주기 때문에
4. 
이벤트 리스너 함수의 콜백함수 this는
실행 도중에 window에서
이벤트 객체 button으로 변한다는 말씀으로
이해해도 되는지 질문드리고 싶습니다


window에서 변한다기보다는 그냥 this가 바로 button이 되는 겁니다. 호출할 때 this를 정하는 것이고, 아무 조작이 없으면 window가 되고, 조작이 있으면 그걸로 변하는 겁니다.

강사님 혹시 이렇게 이해해도 되나요?

만약에 소스코드가 1행부터 5행까지 있으면

소스코드가 첫줄부터 차례대로 실행되는데
예를 들면 중간에 3번째 줄의 함수가 라이브러리에서 구현되어 있는 함수면

그 라이브러리로 건너뛰어서 해당 함수를 구현한 코드를 수행하고

전부 마치면 다시 원래대로 3행으로 돌아오고 다시 순서대로 실행하듯이


제 눈에는 이벤트리스너를 조작한 코드가 보이지 않지만

자바스크립트 기본 내장된 라이브러리에서

이벤트 리스너 함수를 조작한 C++ 코드가 있어서

이벤트 리스너 함수를 실행하는 차례에

그 이벤트 리스너 함수를 조작한 라이브러리의 코드가 실행이 되어서

제 눈에는 조작된 코드가 안보이지만, 자동으로 조작이 되는 원리인가요?

네 이벤트가 발생할 때 c++에서 이벤트리스너에 등록된 콜백에 this를 바꿔서 실행해주는 겁니다.

강사님 너무 많은 질문을 받아주시고 가르쳐주셔서 감사합니다