자바스크립트 This 이해하기

자바스크립트와 This

자바스크립트는 컴파일 과정을 필요로 하지 않는 스크립트 언어이다. 인터프러터(웹 브라우저 등)가 코드를 읽고 행 by 행으로 자바스크립트를 실행 시킨다. 이 때 각각의 코드가 실행되는 환경-aka scope(범위)- 을 실행 컨텍스트(Execution Context)라고 표현한다. 여러개의 실행 컨텍스트는 자바스크립트 런타임 상에 존재하다가 코드가 실행되는 순간에 스택의 최상단에 위치하게 된다.

This 키워드는 자신이 불린 곳에 속하는 객체를 가리키는데, This 키워드가 가리키는 오브젝트 또한 실행 컨텍스트가 바뀜에 따라 변화하며 THIS는 동적으로 결정되게 된다.

덧붙여 말하면, 자바스크립트는 싱글 스레드 기반 언어이기 때문에 한 번에 하나의 작업(스택)만 처리할 수 있다. (자바스크립트 실행환경에 대한 세한 설명은 아래 링크에 잘 나와있으니 꼭 참고해보도록 하자.) 자바스크립트의 동작원리: 엔진, 런타임, 호출 스택

브라우저 환경에서 this를 전역에서 사용하면 전역 객체인 Window를 가리킨다. NodeJS상에서 this는 global을 가리킨다.

//top level(browser)
this === window; // true
("use strict");
this === window; // true

함수에서 this를 사용하면 this는 전역 객체, 즉 브라우저 상에서 window를 가리킨다.

function FairyTale(author, book) {
  this.author = author;
  this.book = book;
}

const Story1 = FairyTale("Anderson", "The Little Mermaid");

console.log(window.author); // 'Anderson'
console.log(window.book); // 'The Little Mermaid'
console.log(Story1.author); // TypeError: Cannot read property 'author' of undefined

코드를 쓰는 사람 입장에서는 당연히 Story1.author를 했을때 원하는 결과가 나오길 바랄 것이다. 그러나 현실은 window객체에 묶어주어야만 사용자가 생각하는 결과가 출력된다. 프로토타입 객체와 연결된 객체를 반환하려면 new 키워드와 함께 호출해준다.

const Story2 = new FairyTale("Oscar Wilde", "The Happy Prince");

console.log(Story2.author); // 'Oscar Wilde'

Strict Mode와 This

function checkThis() {
  console.log("checkthis", this); //window객체
}

function checkThis2() {
  "use strict";
  console.log("checkthis2", this); //undefined
}

checkThis(); // 함수에서 this를 사용하고 호출하면 this는 전역 객체를 가리킨다.
checkThis2(); // strict mode에서 this는 undefined가 된다.

이 포스트의 상단 부분에서 가장 top level에서 this를 호출했을 때는 strict mode 여부에 관계없이 모두 윈도우 객체를 가리켰다. 그런데 여기선 왜 결과가 다를까?

그 이유는 바로 위에서 설명한 this의 특성과 관계가 있다. new 키워드 없이 호출할 시 this는 전역 객체를 가리킨다. 그리고 strict mode가 도입되기 이전인 ES3까지 그 출력값은 전역 객체로 반환되었다. 그러나 이러한 behavior는 글로벌 오브젝트에 변수를 마구 덧붙여버리는 불상사를 낳게 되었고 아마 ECMA에서 이를 개선시킬 필요성을 절감하게 된 것 같다. 따라서 이 이후부터는 ES5부터 strict mode 가 추가되었고 strict mode 상에서 new 키워드 없이 함수가 호츌된다면 this를 undefined로 정의하여 버렸다. 자바스크립트도 하나의 언어이듯이 규칙, syntax적인 부분이 자바스크립트 속성에 많이 작용하는 듯 하다.

시간이 되면 arrow function에서의 this에 대해서도 추후 포스팅하겠다.