본문 바로가기

HTML ⁄ CSS ⁄ JS

Javascript - 'this' 키워드로 객체에 접근하기

 

 

this 키워드

this는 객체의 프로퍼티나 메서드를 참조, 변경할 수 있도록 해주는 자기참조변수(self-referencing variable)이다.

생성자 함수로 인스턴스를 생성하려면, 먼저 생성자 함수를 정의해두고, new 연산자와 함께 생성자 함수를 호출해야 한다. 그런데 생성자 함수를 정의하는 시점에는 아직 인스턴스를 생성하기 전이라, 생성자 함수가 생성할 인스턴스를 가리키는 식별자를 알 수 없다. 이 때 this를 사용하면 '미래'에 생성되는 인스턴스의 프로퍼티나 메서드를 참조할 수 있다.

this 바인딩이란, this라는 식별자와 this가 가리킬 객체를 '연결'하는 과정을 의미한다. this 바인딩, 즉 this가 가리키는 값은 함수 '호출 시점'에 함수를 어떻게 호출하는지에 따라 동적으로 결정된다는 점이 특징이다.

 

 

일반함수의 바인딩

함수 호출 방식별 this 바인딩이 어떻게 달라지는지 하나씩 살펴보자.

1. 기본 바인딩(Default Binding)

전역에서 this는 전역객체 window 를 가리킨다.

console.log(this); // window

일반 함수 내부에서 this는 전역객체 window 를 가리킨다.

function addEventListeners() {
  console.log(this); // window
}
addEventListeners();

 

2. 암시적 바인딩(Implicit Binding)

메서드 내부에서 this는 메서드를 호출한 객체 를 가리킨다.

const car = {
  name: 'tico',

  getName() {
    console.log(this); // { name: 'tico', getName: f }
    return this.name; // tico
  },
};
car.getName();

 

3. 명시적 바인딩(Explicit Binding)

앞서 2번에서 살펴보았듯, 어떠한 함수라도 일반 함수로 호출되면 모두 this에 전역 객체 window가 바인딩된다. 중첩함수나 콜백함수의 경우에도 다름 없이 전역 객체가 바인딩된다는 말이다.

프로그래밍 의도에 따라 전역 객체가 아닌 상위 스코프의 this 바인딩과 일치시키고 싶다면 apply, call, bind 메서드를 사용해보자. apply, call, bind 메서드는 모든 함수가 기본적으로 상속받기 때문에 모든 함수에서 사용할 수 있다.

ES5는 함수를 어떻게 호출했는지 상관하지 않고 this 값을 설정할 수 있는 bind 메서드를 도입했다. func.bind(this)를 호출하면 func와 같은 본문()과 범위를 가졌지만 this는 원본 함수를 가진 새로운 함수가 생성된다. 이렇게 생긴 함수는 호출 방식과 상관없이 bind()의 첫 번째 매개변수로 this가 영구적으로 고정된다.

call과 apply는 서로 유사한데, call은 각각의 인수(this, 1, 2, 3)를 apply 인수들의 단일 배열(this, [1, 2, 3])을 받는다는 차이가 있다.

 

 

4. new 바인딩(new Binding)

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

function Car(name) {
  this.name = name;
  this.getName = function() {
    console.log(this); // Car { name: 'tico' }
    return this.name;
  }
}
const myCar = new Car('tico')

 

 

화살표함수의 바인딩

ES2015는 스스로의 this 바인딩을 제공하지 않는 화살표 함수(Arrow Function)을 추가했다. 일반 함수(Regular Function)와 달리 화살표 함수에 내부의 this는 상위 스코프의 this를 가리킨다.

화살표 함수는 call, apply, bind 메소드를 사용하여 this를 변경할 수 없다. 

console.log(this); // Window 전역객체

const car = {
  name: 'tico',

  logNameRegFunc: function () {
    console.log(this); // { name: 'tico', logNameRegFunc: f ... }
    console.log(this.name); // 'tico'
  },
  logNameArrowFunc: () => {
    console.log(this); // Window 전역객체 (상위 스코프의 this)
    console.log(this.name); // ''
  },
};
car.logNameRegFunc();
car.logNameArrowFunc();

 

 

참고자료

- this | MDN
- apply | MDN
- call | MDN
- bind | MDN