ES6알아보기 10 - this

ES6알아보기 10 - this

2018, Jul 08    

this 란

Javascript 로 만들어지는 모든 프로그램은 각각의 객체 로 구성되어 있습니다. 그리고 이 객체가 자기 스스로를 지칭하는 구문을 this 라고 합니다. 우선 ES6이전과 이후의 this의 차이점을 알아보기 이전에 일반적인 사용법을 알아보도록 하겠습니다.


기본적인 사용법

var obj = {
  hello: 'hello world!',
  print: function() {
    console.log(this.hello);
    if (this === obj) console.log('this is obj');
    if (this === window) console.log('this is window');
  }
}
obj.print();
// hello world!
// this is obj

위의 예에서 볼 수 있듯이 obj 란 객체를 선언했습니다. obj 객체 안에 메소드를 추가했고 그 메소드 안에서 this를 부를 경우 이 this는 obj객체 자신 을 지칭하는 구문이 됩니다.

그렇다면 객체를 따로 선언하지 않고 바깥에서는 사용할 경우 무엇을 지칭하게 될까요?


global 객체에서의 사용법

function print() {
  if (this === window) console.log('this is window');
  if (this === global) console.log('this is global');
}
print()
// browser 에서 실행할 경우 // this is window
// node.js 에서 실행할 경우 // this is global

이번에는 print()라는 함수를 바깥으로 꺼내 정의 후 실행해 보았습니다. this 라는 구문은 자신이 소속된 곳을 지칭하는 구문이기 때문에 이 경우도 역시 마찬가지로 자신이 속한 객체를 지칭합니다. 그리고 이 객체는 브라우서에서 실행할 경우는 window , node.js에서 실행할 경우는 global 객체를 지칭하게 됩니다.

사실 눈에 보이지는 않지만 우리가 선언하는 모든 객체는 상위 객체에 소속하게 됩니다. print() 라는 함수를 선언할 경우 정확이 얘기하자면 window.print() 처럼 상위객체인 window 객체에 속한 메소드로 정의 됩니다.


ES6에서의 this

사실 ES6부터 this 구문 자체의 역활이 달라졌다기 보다는 arrow function (화살표 함수) 안에서 사용할 경우 this 가 가르키는 객체가 달라진다는 점 입니다. 아래의 예를 통해 어떻게 달라지는지 차이를 알아보겠습니다.

위에서 사용한 예제에서 print 메소드를 arrow function 으로 변경해서 실행해보면 결과는 다음과 같습니다.

var obj = {
  hello: 'hello world!',
  print: () => {
    console.log(this.hello);
    if (this === obj) console.log('this is obj');
    if (this === window) console.log('this is window');
  }
}
obj.print();
// undefined
// this is window

차이를 아시겠나요? arrow function 에서의 this는 메소드가 소속된 객체를 지칭하지 않습니다. 위의 경우에는 obj 객체의 상위객체인 windows(브라우저에서 실행했을 경우) 를 가리키게 되기 때문에 print 메소드를 실행했을 때 위와 같은 결과가 출력되었습니다.

이 차이는 일반 함수와 화살표 함수의 특징의 차이라고 할 수 있습니다.

일반 함수는 callableconstructible 이라는 특징을 가지고 있습니다. callable 은 함수가 생성된 이 후 그 함수를 불러서 {} 스코프 안에 정의된 처리들을 실행시킬 수 있다는 의미이고 constructible 은 새로운 객체로써 생성될 수 있다는 의미입니다. 우리가 흔히 알듯이 new 구문을 사용해서 객체를 생성할 수 있다는 의미 입니다.

하지만 arrow functioncallable 의 특징만 가지고 있습니다. new 구문을 통해 객체로써 생성될 수 없다는 말이지요. 객체로써 생성될 필요가 없기 때문에 this를 바인딩 할 필요도 없어지게 됩니다. 이러한 이유때문에 위와 같은 결과를 출력하게 됩니다.


callable 과 constructible

이번에는 callableconstructible 의 경우 this의 차이의 대해 살펴보겠습니다.

  • callable - 함수의 {} 스코프에 정의된 처리들을 실행
  • constructible - new 구문을 이용해서 새로운 함수 객체를 생성

이 두가지 경우에도 this에 바인딩 되는 컨텍스트는 달라지게 됩니다.

function person() {
  console.log(this)
}

person() // browser의 경우 this에는 window, node.js 의 경우 global 이 바인딩
new person() // person 객채가 this 에 바인딩

중요한 것은 누가 주체가 되어 이 함수를 부르는 것인가 를 보시면 될 것 같습니다.

person() 의 경우 실행하는 관점이 상위 객체 Window 의 메소드로써 call 하는 것이기 때문에 부르고 있는 주체인 Window 가 바인딩됩니다.
new person() 의 경우 스스로가 주체가 되어 함수를 생성자로 사용하고 있는 것이기 때문에 주체가 되는 person 이 바인딩되게 됩니다.