[Deep Dive] This

link717·2021년 9월 22일
0

Deep Dive

목록 보기
4/28
post-thumbnail

🌼 22.1 This 키워드

객체지향 프로그래밍에서 객체는 상태를 나타내는 프로퍼티와 동작을 나타내는 메서드를 하나의 논리 구조로 묶은 복합적인 자료구조이다. 이 자료구조에서 메서드는 자신이 속한 객체를 가리키는 식별자를 참조할 수 있어야 한다. 또한 생성자 함수 내부에서는 프로퍼티 또는 메서드를 추가하기 위해서 자신이 생성할 인스턴스를 참조할 수 있어야 한다. 하지만 생성자 함수를 정의하는 시점에는 아직 인스턴스를 생성하기 이전이므로 생성자 함수가 생성할 인스턴스를 가리키는 식별자를 알 수 없다. 따라서 자신이 속한 객체 또는 자신이 생성할 인스턴스를 가리키는 특수한 식별자가 필요한데 자바 스크립트를 이러한 식별자를 this라는 키워드로 제공한다.

  • this는 자신이 속한 객체 또는 자신이 생성할 인스턴스를 가리키는 자기 참조 변수(self-referencing variable)이다.

  • this를 통해 자신이 속한 객체 혹은 자신이 생성할 인스턴스를 참조할 수 있다.

  • this는 자바스크립트 엔진에 의해 암묵적으로 생성된다.

  • this 바인딩은 함수 호출 방식에 의해 동적으로 결정된다.

    • 자바나 C++ 같은 클래스 기반 언어에서 this는 언제나 클래스가 생성하는 인스턴스를 가리킨다. 하지만 자바스크립트의 this는 함수가 호출되는 방식에 따라 this에 바인딩될 값, 즉 this 바인딩이 동적으로 결정된다.

    • stric mode에서 일반 함수의 this는 undefined가 바인딩된다.


🌼 22.2 함수 호출 방식과 this 바인딩

  • 일반 함수 호출: 기본적으로 this에 전역 객체가 바인딩된다. 기본적으로 일반 함수 내에서 this는 의미가 없다. 메서드 내에서 정의한 중첩함수도 콜백함수도 일반함수로 호출되면 this는 전역 객체이다. 하지만 외부 함수인 메서드와 중첩 함수 또는 콜백 함수의 this가 일치하지 않는다는 것은 이들이 헬퍼함수로서 동작하기 어렵게 만든다. this 바인딩을 일치시키기 위한 방법은 다음과 같다.

    • this를 다른 변수에 담아 해당 변수로 접근하는 방법

    • 화살표 함수를 사용하여 상위 스코프의 this를 바인딩시키는 방법

    • this를 명시적으로 바인딩할 수 있는 메서드를 사용하는 방법

let value = 1;

const obj = {
  value: 100,
  foo() {
    //this(obj)를 변수 that에 할당한다.
    const that = this;
    console.log("foo's this", this);

    setTimeout(function () {
      console.log("callback's this", that);
      console.log("callback's value", that.value);
    }, 100);

    // 화살표 함수의 this는 상위 스코프의 this를 가리킨다.
    setTimeout(() => {
      console.log("arrow's this", this);
      console.log("arrow's value", this.value);
    }, 1000);
  },
};

obj.foo();
  • 메서드 호출: 메서드 내부의 this는 메서드가 호출될 때 마침표(.) 앞의 객체가 바인딩된다. 이 때 메서드 내부의 this는 메서드를 소유한 객체가 아닌 메서드를 호출한 객체에 바인딩된다.

  • 생성자 함수 호출: 생성자 함수 내부의 this에는 생성자 함수가 생성할 인스턴스가 바인딩된다. 다만 new 연산자와 함께 호출하지 않으면 생성자 함수가 아니라 일반 함수로 동작한다.

  • Function.prototype.apply/call/bind 메서드에 의한 간접 호출

function getThisBinding() {
  console.log(arguments);
  return this;
}

const thisArg = { a: 1 };

// call은 첫번째 인자로 this로 바인딩할 객체를 받는다.
// 호출할 함수의 인수를 쉼표로 구분한 리스트 형식으로 받는다.
console.log(getThisBinding.call(thisArg, 1, 2, 3));

// apply는 첫번째 인자로 this로 바인딩할 객체를 받는다.
// 호출할 함수의 인수를 배열 형식으로 받는다.
console.log(getThisBinding.apply(thisArg, [1, 2, 3]));

// bind는 함수에 this로 사용할 객체를 전달한다.
// call, apply와 다르게 함수를 호출하지 않는다.
console.log(getThisBinding.bind(thisArg));

출처: 모던 자바 스크립트 Deep Dive-이웅모

profile
Turtle Never stop

0개의 댓글