관리 메뉴

Jerry

자바스크립트, this란?? 🤷‍♂️🧐🤷‍♂️🧐🤷‍♂️🧐 본문

Front/JavaScript

자바스크립트, this란?? 🤷‍♂️🧐🤷‍♂️🧐🤷‍♂️🧐

juicyjerry 2021. 4. 20. 16:03
반응형
참고로, 이 글은 인프런, Javascript 핵심 개념 알아보기 - JS Flow, 정재남 강의를 보고서 정리한 내용입니다.

 

지난 시간에 실행 콘텍스트에 대해 이야기를 하였다. (실행 콘텍스트 글 보기)

실행 콘텍스트에 대한 내용을 보았다면, 아래 이미지가 생소하진 않을 것이다.

(만약, 못 보신 분들이라면 실행 콘텍스트 글을 보고 이 글을 보시는걸 권장드립니다 ) 

 

this라는 개념이 자바스크립트를 처음 접할 때부터 복잡하고 어려운 개념이었다.. 

이번 시간을 통해 this를 뿌셔보도록 하자!!! crushing 'this' !!

 

출처: pixabay.com/images/id-60527/

 


 

지난 시간에 아래 내용 중 ThisBinding에 대해서는 이야기하지 않았는데 이번 시간에 다룰 것이다.

 

 

 

ThisBiding은 어디서 한다? 실행 콘텍스트가 활성화될 때 THIS를 Biding 한다.

실행 콘텍스트가 언제 생성될까? 바로, 이 콘텍스트를 지닌 함수가 실행될 때 활성화됩니다. 

this는 즉, 함수가 실행될 때 활성화됩니다. 

 

 

 

코드의 문맥을 보고 이것의 this는 무엇이다라고 예측할 수 있는 것이 아니라 이 함수를 어떤 식으로 호출했느냐에 따라서 달라진다.

그럼 여기서 어떤 식(종류)에 대해서 살펴보자.

 

 

 

 

0. 전역 공간에서 this 호출시, this는 무얼 가리킬까?

전역 공간에서는 브라우저에서는 window, Node.js에서는 global를 가리킨다. 왜냐하면, 개념상 전역 콘텍스트를 실행시키는 주체가 전역 객체다. 

 

 

왼: browser의 window객체, 우: node.js의 global 객체

 

 

윈도우와 글로벌은 ECMAScript에서 정의한 객체가 아니고 ECMAScript에서 정의되어 있는 전역 객체 개념에 따라 만들어놓은 구현체다. 전역 객체를 어떻게 정의하느냐에 따라 생김새는 달라질 수 있다. 

 

정리하면, 전역 공간에서 this는 전역 객체를 가리킨다!

 

 

1. 함수에서 this를 호출시,  this는 무얼 가리킬까?

함수를 호출 했을 때도 this를 가리킨다. 이상하다고 이야기를 많이 하는데.. 

근데 잘 생각해보면, 함수를 실행하는 순간에 얘를 실행한 주체는 누구냐?

전역 공간에서 a라는 함수를 실행하기 때문에 그러기 때문에 전역 공간이 this로 바인딩된다!

 

 

 

 

그렇다면 이런 함수는 어떨까?

 

 

 

 

그렇다면 함수 c는 어떨까? 뭐가 this에 바인딩될까???

여기서도 this는 전역 공간이 바인딩이 되는데.. 이 부분은 자바스크립트 창시자도 잘못 만들었다고 이야길 한다고 한다. 

 

근데.. 필자는 설마 해서 직접 크롬 개발자 도구를 열어 직접 확인해보았다!

 

 

 

진짜였다... 

 

 

이 부분에 대해서 버그라고 봐야 될지 자바스크립트 자체 특성이라고 봐야 할지 의견이 분분한데.. 

 

es6에서 this 바인딩을 하지 않는 arrow function이 나와서 바로 위에 있는 콘텍스트의 this를 가져다 쓸 수 있게 되었다. 

안타깝게도, es5 환경에서 함수로서 호출했을 때, this는 window 전역 객체를 호출할 수밖에 없다.

 

 

위에서 함수에서 this를 호출할 때 this가 전역객체를 가리킨다고 했는데, 이걸 '함수는 (전역 객체의) 메서드다!'라고 생각하면 편하다고 한다. 

 

 

그렇다면 이번 코드는 어떨까?

메서드가 있고 그 안에 함수가 존재한다.  그럴 때는 어떻게 할까? 

 

 

 

그럴 때는 바로 밑에 함수로서 실행이 되었는지 호출된 형태를 확인을 해보면 된다. 

아래 highlight 된 부분을 보면, 함수로서 호출이 된 것을 알 수 있다. 

그래서 함수 f의 this는 window(전역 객체)를 가리킨다! 

 

 

 

 

 

2. 메서드에서 this를 호출 시, this는 무얼 가리킬까?

메서드 호출 주체가 this가 된다.
.(점) 앞에 있는 것이 this
다. 

 

 

 

 

 

그렇다면 이번 경우는 어떨까?

 

이때는 a.b가 this가 된다. 

 

 

한 가지 더!

텍스트 에디터에서 색깔로 this를 구분해주고 있다고 한다. 

 

 

 

 

내부 함수에서의 우회 법

 

위에서 내부 함수에서 this가 전역 객체를 가리키는 안타까운 상황이 있었다. 메서드의 경우에 이런 상황이 일어나지 않게 하는 법이 있다고 한다.

 

아래 코드를 살펴보자!

아래 obj.b의 this는 obj를 가리킬 것이다. 그렇지만, obj 안 함수 b 안에 있는 내부 함수 c는 어떨까? 

보아하니 함수 c는 호출하는 형태를 보아 함수로서 호출하는 것이므로 내부 함수 c에서 this는 전역 객체를 가리키게 된다.

덩달아 this객체에 있는. a는 전역 공간의 있는 프로퍼티 a 혹은 전역에 선언된 변수가 된다.  

 

 

난센스적인 상황이 발생되는데 자바스크립트의 버그라고 봐야 하지 않을까??라고 한다.

 

그렇다면, 이런 경우에서 우회하는 방법은 무엇일까?

this를 다른 변수에 담아서 그걸 내부에서 사용하는 것이다!

자주 사용하고 지금까지 통용하는 방법이라고 한다.

 

 

그렇게 되면 내부 함수 c에서 self는 obj를 가리키므로 원하는 대로 바인딩을 할 수 있게 된다.

또한, 위 예시에 나오는 self 말고 다른 변수명을 사용해도 되는데 _this, that 등 여러가지가 있는데 이렇게 많이 통용된다고 한다.

 

 

 

3. callback에서 this를 호출 시, this는 무얼 가리킬까?

 

콜백에서 this를 논하기 전에 call, apply, bind메서드에 대해 알아보고 가자!

 

 

 

a.call(b, 1, 2, 3) : a를 호출할 건데, this는 b로 할 거야! 인자에는 1, 2, 3을 넘긴 채로 호출해! 

a.apply(b, [1, 2, 3]) : a를 호출할건데, 이런 놈들을 적용할 거야! this는 b로 하고 인자는 배열로 실행해!

var c = a.bind(b); c(1, 2, 3); : 새로운 함수를 만들건데, this를 b로 했으면 좋겠다.

var d = a.bind(b, 1, 2); d(3); : 새로운 함수를 만들건데, this는 b고 인자 첫 번째 두 번째까지는 값을 미리 정할게! 나중에 나머지 값을 지정해서 호출하면 그때 실행되게끔 해!

 

 

mdn에 있는 각 메소드의 메타 표기법을 확인해보자!

 

call과 apply는 즉시 호출하지만, bind는 새로운 함수를 생성(currying)하는 것이다!

 

여기까지, 명시적으로 this를 정할 수 있는 방법을 이야기했다.

 

 

콜백 함수에서의 this

돌아와서, 여기서  this는 무엇일까?

직접 생각해보자!

 

 

 

콜백 함수의 this는 바로 '전역 객체'를 가리킨다!

cb가 함수로서 호출되었으니 전역 객체를 가리킨다.

 

그렇다면, 아래 코드는 어떨까?

call 메서드를 이용해서 this를 출력하면, this는 obj를 가리킨다. 

 

다시 말해, this를 호출하는 방식에 따라(지정하는 것에 따라) this가 가리키는 것이 달라진다. 

 

 

 

 

setTimeout 경우

this를 따로 처리하지 않고 있는데, 여기서 this는 전역 객체를 출력한다. 

이럴 경우에는 전역 객체가 아닌 다른 것으로 바꿀 수 있는 방법이 있다.

 

 

바로, bind를 이용하는 것이다!

bind를 적용하면 우선순위가 적용되어서 실행될 때, obj를 this로 하게 한다. 

 

 

 

이벤트 핸들러의 경우

클릭했을 때, this를 호출할 땐 무엇이 나올까?

특별하게 바인딩해준 것이 없다면, 전역 객체가 나오는 게 맞을 것이다. 하지만 여기선 dom 엘리먼트가 this로 찍힌다. 

addEventListener가 콜백함수를 처리할 때, this를 이벤트가 발생하는 해당 타깃으로 정하게끔 정의가 되어 있어서 그렇다.

 

 

 

 

이럴 때에도, 내가 원하는 obj가 나오게 하고 싶다면 이렇게 하면 된다.

 

정리해보면, 

  • 기본적으로 함수의 this와 같다.
  • 제어권을 가진 함수가 callback의 this를 명시한 경우 그에 따른다.
  • 개발자가 this를 바인딩한 채로 callback을 넘기면 그에 따른다.

 

 

 

4. 생성자함수에서 this를 호출 시, this를 무얼 가리킬까?

new 하고 함수를 호출하는 함수인데, 새로운 인스턴스를 만드는데...

생성자 함수에서 this는 인스턴스 자체를 가리킨다.

 

Person 함수 안에서 this를 사용하고 있는데 여기서 this는 전역 객체를 가리킨다. 

근데, new를 넣고 나면, 고무곰이라고 새로 생성되는 인스턴스 자체를 this가 가리킨다. 

 

 

 

 

이상으로, 호출을 어떤 식으로 하느냐에 따라서 this가 달라지는 꼼꼼히 살펴보았다.

this라는 개념이 자바스크립트를 처음 접할 때부터 현재까지 어렵고 부담스러운 개념이었는데 이번 시간을 통해서 this 라는 묵혀둔 응어리가 떨어져 나가는거 같아 한편으로는 후련하기도 하다. this는 어쩔 수 없이 외워야 하는 내용도 있는터라 생각날 때마다 들러서 살펴봐야겠다! 이상으로 this 정리는 여기까지 하겠다! 

 

 

 

 

 

반응형

'Front > JavaScript' 카테고리의 다른 글

클로저(CLOSURE)란??  (0) 2021.04.22
callback function(콜백 함수)란??  (0) 2021.04.21
실행 콘텍스트(Execution Context)란?  (0) 2021.04.19
이벤트 루프란? (in Javascript)  (2) 2021.04.16
async 예외처리(의 까다로운점?)  (0) 2021.04.15