일반적인 객체지향의 언어에서의 this는 클래스로 생성한 인스턴스 객체를 의미한다. 그러나 자바스크립트의 this는 어디서든 사용할 수 있다. 상황에 따라 this가 바라보는 대상이 달라진다.
이런 애매모한 this는, 함수와 객체(메서드)의 구분이 느슨한 자바스크립트에서 실질적으로 둘을 구분하는 거의 유일한 기능이다.
기본적으로 this는 전역 객체, 즉 window
를 띈다. Node.js 환경에서는 global
이다.
<aside> 💡 this는 함수를 호출할 때 결정된다.
</aside>
자바스크립트의 this는 기본적으로 실행 컨텍스트가 생성될 때 함께 결정된다. 실행 컨텍스트는 함수를 호출할 때 생성되므로, 바꿔 말하면 this는 함수를 호출할 때 결정된다.
<aside> 💡 전역 공간의 this는 전역 객체를 가르킨다.
</aside>
개념상 전역 컨텍스트를 생성하는 주체가 바로 전역 객체이기 때문이다.
❗ 전역변수의 알쓸신잡
전역변수를 선언하면 자바스크립트 엔진은 이를 전역객체의 프로퍼티로 할당한다. 변수이면서 객체의 프로퍼티이기도 한 셈이다.
var a = 1;
console.log(a);
console.log(window.a);
console.log(this.a);
위의 코드는 모두 정상적으로 실행된다. 이는 자바스크립트의 모든 변수는 실은 특정 객체의 프로퍼티로 동작하기 때문이다.
💡 특정 객체란? 실행 컨텍스트는 변수를 수집해서 LexcialEnvironment의 프로퍼티로 저장한다. 이후 어떤 변수를 호출하면, L.E를 조회해서 일치하는 프로퍼티가 있을 경우 그 값을 반환한다. 전역 컨텍스트의 경우 L.E를 조회해서 일치하는 프로퍼티가 있을 경우 그 값을 반환한다.
즉, 전역변수를 선언하면 자바스크립트 엔진은 이를 전역객체의 프로퍼티로 할당한다.
❓ 근데 왜 그냥 a를 호출할때도 1이 나올까? 이는 변수 a에 접근하고자 하면 스코프 체인에서 a를 검색하다가 가장 마지막에 도달하는 전역 스코프의 L.E (전역객체)에서 a라는 프로퍼티를 발견해서 그 값을 반환하기 때문이다.
window.
가 생략된것이라고 여겨도 무방하다.
❓그럼 var로 변수를 선언하지 않고 winodw의 프로퍼티에 직접 할당하더라고 var로 선언한 것과 똑같이 동작할까? 대부분의 경우에는 이 말이 맞다. 그러나 삭제명령일 경우 전역변수의 선언과 전역객체의 프로퍼티 할당이 전혀 다른 경우도 있다. (아래 🔽) 이는 전역변수를 선언하면 자바스크립트 엔진이 자동으로 전역객체의 프로퍼티로 할당하면서 추가적으로 해당 프로퍼티의 configurable 속성(변경 및 삭제 가능성)을 false로 정의하는 것이다. 사용자가 의도치 않게 삭제하는 것을 방지하는 차원에서 마련한 나름의 방어 전략이다.
// 전역변수가 곧 전역객체의 프로퍼티이므로 delete를 사용할 수 있다.
var a = 1;
delete window.a; // false
console.log(a, window.a, this.a); // 1 1 1
var b = 2;
delete b;
console.log(b, window.b, this.b); // 2 2 2
window.c = 3;
delete window.c;
console.log(c, window.c, this.c); // c is not defined