본문 바로가기
JavaScript

[코어 자바스크립트] 2.this의 개념 및 상황별 this 바인딩 원리

by imsoncod 2021. 6. 24.

1. 들어가기 전

바인딩이란? : 프로그램에서 변수들이 갖는 속성이나 값이 결정되는 것입니다.

다른 대부분의 객체지향 언어에서의 this : 클래스로 생성한 인스턴스 객체로, 클래스에서만 사용이 가능합니다.
자바스크립트에서의 this : 상황에 따라 바라보는 대상이 달라지며 어디서든 사용이 가능합니다.

따라서 작동 방식을 잘 이해해야만 혼란을 줄일 수 있습니다.

2. 상황에 따라 달라지는 this

자바스크립트에서의 this는 기본적으로 실행 컨텍스트가 생성될 때 함께 결정됩니다.
실행 컨텍스트는 함수를 호출할 때 생성되므로 this는 함수를 호출할 때 결정된다고 말할 수 있습니다.

전역 공간에서의 this

전역 공간에서 this는 전역 객체를 가리킵니다.

전역 공간에서만 발생하는 특이한 성질

브라우저상에서의 전역객체는 window, NodeJs환경에서의 전역객체는 global입니다.
전역 변수를 선언하면 자바스크립트 엔진은 이를 전역 객체의 프로퍼티로도 할당합니다.

자바스크립트의 모든 변수는 특정 객체(Lexical Environment)의 프로퍼티로서 동작합니다

실행 컨텍스트는 변수를 수집해서 Lexical Environment의 프로퍼티로 저장합니다.

  • 그냥 a가 1로 출력되는 이유는 스코프 체인을 통해 전역객체의 Lexical Environment에 접근하기 때문입니다.
  • window.a와 this.a가 1로 출력되는 이유는 전역객체의 Lexical Environment를 가리키기 때문입니다.

메서드로서 호출할 때 그 메서드 내부에서의 this

  1. 함수 vs 메서드
  • 함수와 메서드를 구분하는 유일한 차이는 독립성입니다, 객체의 프로퍼티에 할당된다고 해서 무조건 메서드가 아니라 객체의 메서드로 호출된 경우에만 메서드로 동작합니다. 그 외에는 함수로 동작합니다.
  • 함수는 그 자체로 독립성을 수행하는 반면, 메서드는 자신을 호출한 객체에 관한 동작을 수행합니다.
  1. 메서드 내부에서의 this
  • 함수 앞에 (.)이 있어 객체를 통해 호출된 경우에만 메서드로서 호출한 것입니다. (혹은 대괄호)
  • 메서드로서 호출할 경우 this의 호출주체는 (.)앞의 객체입니다.

  1. 함수로서 호출할 때 그 함수 내부에서의 this
  • 실행 컨텍스트를 활성화할 당시에 this가 지정되지 않은 경우 this는 전역객체를 가리킵니다.
  • 메서드가 아닌 함수에서의 호출시에는 무조건 this가 전역객체를 가리킵니다.

메서드의 내부 함수에서의 this를 우회하는 방법

  • 변수를 검색하면 가까운 스코프의 Lexical Environment를 탐색하듯이, this도 가리키는 곳을 변경할 수 없을까?
    ex) var self = this;
    -> 임의의 변수에 this를 담아 넘겨줌으로써 변경할 수 있습니다.

  • ES6에서는 화살표 함수(Arrow Function)을 활용함으로써 스코프체인상 가장 가까운 this에 접근할 수 있습니다.

    (this를 바인딩하는 과정이 제외되었습니다.)

콜백함수 호출 시 그 함수 내부에서의 this

대상이 될 객체를 명시적으로 지정하지 않은 경우 일반적으로 전역객체를 가리킵니다.

생성자 함수 내부에서의 this

어떤 함수가 생성자 함수로써 호출된 경우 내부에서의 this는 새로 생성될 인스턴스 자신이 됩니다.

3. 명시적으로 this를 바인딩하는 방법

call과 apply 메서드

  • 호출 주체인 함수를 즉시 실행하도록 하는 명령어입니다.
  • 첫 번째 인자를 this로 바인딩하고 이후의 인자들을 호출할 함수의 매개변수로 사용합니다.
  • 두 메서드의 차이가 있다면 call메서드는 첫 번째 인자를 제외한 모든 인자들을 매개변수로 지정하지만 apply메서드는 두 번째 인자를 배열로 받아 그 요소들을 매개변수로 지정합니다.

bind 메서드

  • call과 비슷하지만 즉시 호출하지는 않고 넘겨 받은 this 및 인수들을 바탕으로 새로운 함수를 반환하기만 하는 메서드입니다.
  • 새로운 함수를 호출할 때 인수를 넘기면 bind함수를 호출할 때 전달했던 인수들의 뒤에 이어서 등록됩니다.
  • this를 미리 적용하는 것부분적용함수를 구현하는 두 가지 목적을 지닙니다.


왜 부분 적용함수라고 부르지? : 함수 매개변수의 일정부분만을 적용해서 그런가?
line 6에서 this를 미리 적용한 것이고 line 9에서 this적용과 함께 부분 적용함수를 구현한 것입니다.

bind메서드를 적용한 함수의 특이한 성질

name 프로퍼티를 출력해보면 bound라는 접두어가 붙습니다.

4. 정리 (사실상 이걸 보는게 제일 깔끔...)

명시적 this 바인딩이 없는 한 성립하는 원리

  • 전역 공간에서의 this는 전역객체(브라우저 : window, NodeJs : global)를 참조합니다.
  • 어떤 함수를 메서드로써 호출한 경우 메서드명 앞의 객체를 참조합니다.
  • 어떤 함수를 함수로써 호출한 경우 this는 전역객체를 참조합니다.
  • 콜백 함수 내부에서의 this는 해당 콜백 함수의 제어권을 넘겨받은 함수가 정의한 바에 따르며, 정의하지 않은 경우에는 전역객체를 참조합니다.
  • 생성자 함수에서의 this는 생성될 인스턴스(자기 자신)를 참조합니다.

명시적 this 바인딩

  • call, apply 메서드는 첫 번째 인자를 통해 this를 명시적으로 지정하면서 함수 또는 메서드를 호출합니다.
  • bind 메서드는 this 및 함수에 넘길 인수를 부분 지정해서 새로운 함수를 만듭니다.
    → this 미리 적용과 부분 적용함수 구현의 역할을 합니다.
  • 요소를 순회하면서 콜백 함수를 반복 호출하는 내용의 일부 메서드는 별도의 인자로 this를 받기도 합니다.
    ex) forEach
반응형

댓글