[코어 자바스크립트] 3장 this

Dochaki·2024년 10월 2일

코어자바스크립트

목록 보기
3/7
post-thumbnail

3장 this

3-1 상황에 따 달라지는 this

  • js에서 this는 실행 컨텍스트가 생성될 때 함께 결정됨.
    • 실행컨텍스트는 함수를 호출할 때 생성되므로 this는 함수를 호출할 때 결정됨

3-1-1 전역공간에서의 this

  • 전역 공간에서는 this 가 전역 객체를 가르킴
    • 브라우저에서는 window
    • Node.js에서는 global
var a = 1;
console.log(a); // 1
console.log(window.a); // 1
console.log(this.a); // 1
  • 위와 같이 뜨는 이유는 js의 모든 변수는 실행 컨텍스트의 LexicalEnnvironment의 프로퍼티로 동작하기 때문.
    • 전역 변수 선언시, js는 전역 객체의 프로퍼티로 할당함
var a = 1;
delete window.a; // false

var b = 2;
delete b; // false

window.c = 3;
delete window.c; // true

window.d = 4;
delete d; // true
  • 처음부터 전역객체의 프로퍼티로 할당했으면 삭제 O
  • 전역변수로 선언한 경우에는 삭제 X

3-1-2 메서드로서 호출할 때 그 메서드 내부에서의 this

  • 함수 vs 메서드
    • 함수와 메서드를 구분하는 것은 독립성에 있음
    • 함수는 그 자체로 독립적인 기능 수행
    • 메서드는 자신이 호출한 대상 객체에 관한 동작 수행
var func = function (x) {
  console.log(this, x);
};
func(1); // Window {...} 1

var obj = {
  method: func,
};
obj.method(2); // {method: f} 2
  • 1은 함수로서 호출

  • 2는 메서드로서 호출

  • 이 둘을 구분하는 방법은 함수 앞에 .(점) 이 있는 지 여부로 구분

  • 메서드 내부에서의 this

    • this에는 호출한 주체에 대한 정보가 담김
    • 어떤 함수를 메서드로서 호출하는 경우 호출 주체는 함수명 앞의 객체.
    • 점 표기법의 경우는 마지막 점 앞에 명시된 객체가 this가 됨.

3-1-3 함수로서 호출할 때 그 함수 내부에서의 this

  • 함수 내부에서의 this

    • 어떤 함수를 함수로서 호출할 경우는 this가 지정되지 않음.
    • this는 전역 객체를 가르킴
  • 메서드의 내부함수에서의 this

    var obj1 = {
      outer: function () {
        console.log(this); // (1)
        var innerFunc = function () {
          console.log(this); // (2) (3)
        };
        innerFunc();
    
        var obj2 = {
          innerMethod: innerFunc,
        };
        obj2.innerMethod();
      },
    };
    obj1.outer();
    • (1): obj1, (2): 전역객체(Window), (3): obj2 출력
    • outer 메서드 내부에 있는 함수(innerFunc)를 함수로서 호출하고, obj2.innerMethod(); 같은 함수를 메서드로서 호출함. 이처럼 같은 함수여도 바인딩되는 this의 대상이 달라짐.
    • this 바인딩은 함수를 실행하는 당시의 주변 환경(메서드 내부인지, 함수 내부인지)는 중요하지 않고, 오직 해당 함수를 호출하는 구문 앞에 점 또는 대괄호 표기가 있는지의 여부가 관건
  • 메서드의 내부 함수에서의 this를 우회하는 방법

    • 변수를 활용하는 것
    • 상위 스코프의 this를 변수에 저장해 내부 함수에서 활용.
    var obj1 = {
      outer: function () {
        console.log(this); // (1) {outer: f}
        var innerFunc = function () {
          console.log(this); // (2) Window {...}
        };
        innerFunc();
    
        var self = this;
        var innerFunc2 = function () {
          console.log(self); // (3) { outer: f }
        };
        innerFunc2();
      },
    };
    obj1.outer();
  • this를 바인딩하지 않는 함수

    • var obj1 = {
        outer: function () {
          console.log(this); // (1) {outer: f}
          var innerFunc = () => {
            console.log(this); // (1) {outer: f}
          };
          innerFunc();
        },
      };
      obj1.outer();
    • 함수가 호출될 때 this 컨텍스트가 바인딩되지 않도록 하려면 일반적으로 화살표 함수를 사용
    • 화살표 함수는 함수가 정의된 시점에서 상위 스코프의 this를 캡처하기 때문에 함수가 호출될 때 this가 변경되지 않음.

3-1-4 콜백 함수 호출 시 그 함수 내부에서의 this

  • 콜백 함수도 함수이기 때문에 기본적으로는 this가 전역 객체를 참조
  • 제어권을 받은 함수에서 콜백 함수에 별도로 this가 될 대상을 지정한 경우에는 그 대상을 가리킴

3-1-5 생성자 함수 내부에서의 this

  • 생성자는 구체적인 인스턴스를 만들기 위한 일종의 틀임.
  • 생성자 함수는 공통된 성질을 지니는 객체들을 생성하는 데 사용하는 함수로, new 명령어와 함께 함수를 호출하면 해당 함수가 생성자 함수로서 동작.
  • 생성자 함수로서 호출되는 경우 내부에서의 this는 곧 새로 만들 구체적인 인스턴스 자신이 됨.

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

3-2-1 call 메서드

  • Function.prototype.call(thisarg [, arg1[, arg2[, ...]]])
    • call 메서드는 메서드의 호출 주체인 함수를 즉시 실행하도록 하는 명령
    • 이때 call 메서드의 첫 번째 인자를 this로 바인딩하고, 이후의 인자들을 호출할 함수의 매개변수로 함.

3-2-2 apply 메서드

  • Function.prototype.apply(thisarg [, argsArray])
    • apply는 call과 기능적으로 완전히 동일
    • 두 번째 인자를 배열로 받아 그 배열의 요소들을 호출할 함수의 매개변수로 지정한다는 점이 차이점.

3-2-3 call / apply 메서드의 활용

  1. 유사배열 객체에 배열 메서드를 적용
    • ES6에서는 유사배열객체 또는 순회 가능한 모든 종류의 데이터 타입을 배열로 전환하는 Array.from을 도입
  2. 생성자 내부에서 다른 생성자를 호출
    • 생성자 내부에 다른 생성자와 공통된 내용이 있을 경우에 call or apply를 이용해 다른 생성자를 호출하면 간단하게 반복을 줄일 수 있음
  3. 여러 인수를 묶어 하나의 배열로 전달하고 싶을 때 - apply 활용
    • ES6에서는 spread operator를 이용하면 apply를 적용하는 것보다 간편하게 작성 가능

3-2-4 bind 메서드

  • Function.prototype.bind(thisarg [, arg1[, arg2[, ...]]])
  • ES5에서 추가된 기능으로, call 메서드와 비슷하지만 즉시 호출하지 않고, this 및 인수들을 바탕으로 새로운 함수를 반환하는 메서드
  • (1) 함수에 this를 미리 적용, (2) 부분 적용 함수를 구현하는 2가지의 목적
  • name 프로퍼티
    • bind 메서드를 적용해서 새로 만든 함수는 name 프로퍼티에 동사 bind의 수동태인 'bound'라는 접두어가 붙음
    • 기존의 call이나 apply보다 코드를 추적하기 쉬움
  • 상위 컨텍스트의 this를 내부함수나 콜백 함수에 전달하기
    • 변수를 활용하여 우회하는 방법도 있지만, call, apply, bind 메서드를 사용하면 더 깔끔하게 처리 가능함.
    • 콜백 함수를 인자로 받는 함수나 메서드 중에서 기본적으로 콜백 함수 내에서의 this에 관여하는 함수 또는 메서드에 대해서도 bind 메서드를 이용하면 this 값을 사용자에 맞춰서 바꿀 수 있음

3-2-5 화살표 함수의 예외사항

  • 화살표 함수 내부에는 this가 아예 없으며, 접근하고자 하면 스코프체인 상 가장 가까운 this에 접근하게 됨

3-2-6 별도의 인자로 this를 받는 경우(콜백 함수 내에서의 this)

  • 내부 요소에 대해 같은 동작을 반복 수행해야 하는 배열 메서드에 많이 포진돼있음.
  • 콜백 함수를 인자로 받는 메서드 중 일부는 추가로 this로 지정할 객체(thisArg)를 인자로 지정할 수 있는 경우가 있음
  • ex) forEach, map, filter, some, every, find, findIndex, flatMap, from

정리

  • 명시적 this 바인딩이 없을 때 성립하는 규칙

    • 전역 공간에서의 this는 전역 객체(브라우저에서는 Window, Node.js에서는 global)를 참조
    • 어떤 함수를 메소드로서 호출한 경우, this는 메서드 호출 주체(메서드명 앞의 객체)를 참조
    • 어떤 함수를 함수로서 호출한 경우, this는 전역 객체를 참조하며 메서드의 내부함수에서도 동일
    • 콜백 함수 내부에서의 this는 해당 콜백 함수의 제어권을 넘겨 받은 함수가 정의한 바에 따르며, 정의하지 않은 경우 전역객체를 참조
    • 생성자 함수에서의 this는 생성될 인스턴스를 참조
  • 명시적 this 바인딩

    • call, apply 메서드는 this를 명시적으로 지정하면서 함수 또는 메서드를 호출
    • bind 메서드는 this 및 함수에 넘길 인수를 일부 지정해 새로운 함수 생성
    • 요소를 순회하며 콜백 함수를 반복 호출하는 내용의 일부 메서드는 별도의 인자로 this를 받기도 함
  • this가 결정되는 시점

    • this란 자신이 속한 객체를 의미하며 보통 this는 함수를 호출하는 시점에 결정되지만 화살표 함수에서는 this가 lexical this로 결정되며 일부 상황에서는 call, apply, bind 등의 메소드로 명시적으로 this를 지정

0개의 댓글