그동안 실행 컨텍스트에 대해 들어봤고, 얼추 알고 있었지만 설명할 수 있냐에 대한 질문에는 답변을 하지 못했을 것 같습니다. 그래서 이번 기회에 실행 컨텍스트에 대해 정리해 보는 시간을 가지려 합니다.
실행 컨텍스트란, 실행할 코드에 환경 정보를 모아놓은 객체입니다. 실행 컨텍스트를 구성하는 요소는 아래와 같습니다.
위 정보를 가진 컨텍스트를 콜스택에 쌓아올리게 됩니다. 스택(Last In First Out) 이니 만큼, 가장 위에 쌓여있는 컨텍스트와 관련된 코드를 실행하게 됩니다.
var a = 1;
function funcA() {
function funcB() {
var a = 3;
}
funcB();
}
funcA();
예를 들어 위와 같은 코드가 있다고 하면,
전역(실행) → 전역(실행) → funcA(실행) → funcA(중단) → funcB(실행) → funcB(종료) → funcA(재개) → funcA(종료) → 전역(종료)
의 순서대로 컨텍스트가 실행되게 됩니다.
VariableEnviroment
와 LexicalEnviroment
는 기본적으로 같으며, 아래와 같은 정보를 가지고 있습니다.
컨텍스트 내의 식별자 정보, 이 식별자에 대한 정보를 수집하는 과정에서 호이스팅에 대한 개념이 등장하게 됩니다.
외부 환경에 대한 정보, 즉 이전 컨텍스트의 LexicalEnviroment를 가집니다. 스코프 체이닝의 개념이 여기서 등장하게 됩니다.
VariableEnviroment
와 LexicalEnviroment
는 최초에 생성되는 시점에는 완전히 같은 값을 가집니다만 아래와 같은 차이점이 존재합니다.
snapshot
의 형태로 데이터를 가짐this
는 실행 컨텍스트가 생성될 때 결정되며, 결정된다는 말을 bind
묶는다고 표현하며, 사용되는 환경에 따라 변경됩니다.
전역에서의 this
는 전역 객체를 가르킵니다.
전역 객체는 런타임 환경에 따라 변경되며, 브라우저 환경에서는 window
를, 노드 환경에서는 global
을 가르키게 됩니다.
const obj = {
name: "kkangs",
displayName: function () {
console.log(this.name)
}
}
obj.displayName()
메서드는 주체가 존재합니다.
위와 같은 환경에서의 showThis
는 obj
라는 주체가 존재하기 때문에, this
는 obj
에 해당합니다.
따라서 name
은 kkangs
가 출력되게 됩니다.
const obj = {
funcA: function () {
console.log(this)
function funcB(){
console.log(this)
}
funcB();
}
}
obj.funcA()
함수는 주체가 없는, 독립적인 실행 환경에 해당합니다. 그렇기에 함수에서의 this
는 전역 객체에 해당합니다.
따라서 funcB
는 메소드 내부에 선언되어 있지만 전역 객체를 가리키게 됩니다.
일반 함수와 화살표 함수의 가장 큰 차이점이 뭔가에 대한 가장 적절한 답변은 this binding
의 여부일 것입니다.
const obj = {
funcA: function () {
console.log(this)
const funcB = () => {
console.log(this)
}
funcB();
}
}
obj.funcA()
화살표 함수는 this binding
과정 자체를 생략하기에 기존에 this
였던 obj
를 가르키게 됩니다.
기본적으로 콜백 함수의 this
는 전역 객체를 가르키지만, 예외는 존재합니다.
별도로 this
를 지정한 경우이며 addEventListner
의 경우 호출한 주체를 가르키게 되어 있습니다.