[코어 자바스크립트] 02. 실행 컨텍스트

modi·2023년 10월 19일
0
post-thumbnail

실행 컨텍스트란?

실행 컨텍스트는 실행할 코드에 제공할 환경 정보들을 모아놓은 객체

실행 컨텍스트 실행

  1. 동일한 환경에 있는 코드들을 실행할 때 필요한 환경 정보를 모아서 컨텍스트를 구성한다
    • 동일한 환경: 함수 실행, 전역공간, eval()
  2. 컨텍스트를 콜 스택에 쌓아올린다
  3. 가장 위에 쌓여있는 컨텍스트와 관련 있는 코드들을 실행한다

실행 컨텍스트와 콜 스택

var a = 1;
function outer() {
  function inner() {
    console.log(a); // undefined
    var a = 3;
  }
  inner();
  console.log(a); // 1
}

outer();
console.log(a); // 1

  1. 전역 컨텍스트가 콜 스택에 담긴다
    • 전역 컨텍스트: 자바스크립트 파일이 열리는 순간 활성화
  2. outer 함수 호출 -> outer 실행 컨텍스트가 콜 스택에 담긴다
  3. 전역 컨텍스트 관련 코드 일시중단 && outer 함수 내부 코드 순차적으로 실행
  4. inner 함수 호출 -> inner 실행 컨텍스트가 콜 스택에 담긴다
  5. outer 컨텍스트 관련 코드 일시중단 && inner 함수 내부 코드 순차적으로 실행
  6. inner 함수 종료 -> inner 실행 컨텍스트 콜 스택에서 제거
  7. outer 컨텍스트가 콜 스택 맨 위 -> 중단된 코드 다음 줄부터 이어서 실행
  8. outer 함수 종료 -> outer 실행 컨텍스트 콜 스택에서 제거
  9. 전역 컨텍스트가 콜 스택 맨 위 -> 중단된 코드 다음 줄부터 이어서 실행
  10. 전역 공간 함수 종료 -> 콜 스택에는 아무것도 없이 종료

그렇다면 왜 inner의 a는 undefined일까? 실행 컨텍스트 객체에 대해 더 자세히 알아보자

Variable Environment

  • 최초 실행 시 스냅샷 유지
  • 실행 컨텍스트를 생성할 때 Variable Environment에 정보를 먼저 담음 -> 이를 그대로 복사해 Lexical Environment 생성

Lexical Environment

environment Record와 호이스팅

  • environment Record: 현재 컨텍스트와 관련된 코드의 식별자 정보 저장
  • 컨텍스트 내부 전체를 처음부터 끝까지 훑어나가면 순서대로 수집

호이스팅

호이스팅, 코드가 실행되기 전에 자바스크립트 엔진이 이미 해당 환경에 속한 코드의 변수명을 알고 있다

  • 자바스크립트 엔진은 식별자들을 최상단으로 끌어올려놓은 다음 실제 코드를 실행한다
  • 변수를 호이스팅할 때 변수명만 끌어올리고 할당 과정은 원래 자리에서

호이스팅 규칙에 따라 아래와 같이 출력된다

function a (x) {
  console.log(x); // 1
  var x;
  console.log(x); // 1
  var x = 2;
  console.log(x); // 2
}
a(1);
function a () {
  console.log(b); // b 함수
  var b = 'bbb';
  console.log(b); // bbb
  function b () { }
  console.log(b); // bbb
}
a();

함수 선언문과 함수 표현식

function a () {} // 함수 선언문

var b = function () {} // 익명 함수 표현식. 변수명 b가 곧 함수명

var c = function d () {} // 기명 함수 표현식. 변수명은 c, 함수명은 d.

c(); // 실행
d(); // 에러
  • 함수 선언문은 함수 전체를 호이스팅하지만, 함수 표현식으 변수 선언부만 호이스팅한다

함수 선언문의 위험성
전역 컨텍스트가 활성화될 때 전역공간에 선언된 함수들이 모두 가장 위로 끌어올려진다. 동일한 변수명에 서로 다른 값을 할당할 경우 나중에 할당한 값이 먼저 할당한 값을 덮어씌운다.

스코프, 스코프 체인, outerEnvironmentReference

  • 스코프: 식별자에 대한 유효 범위
  • 스코프 체인: 식별자의 유효범위를 안에서 바깥으로 차례로 검색하는 것
  • LexicalEnvironment의 outerEnvironmentReference를 통해 스코프 체인

스코프 체인

  • outerEnvironmentReference현재 호출된 함수가 선언될 당시의 LexicalEnvironment를 참조
  • outerEnvironmentReference는 연결 리스트의 형태: 선언 시점의 LexicalEnvironment -> 마지막에는 전역 컨텍스트의 LexicalEnvironment
  • 여러 스코프에서 동일한 식별자를 선언한 경우, 무조건 스코프 체인 상에서 가장 먼저 발견된 식별자에만 접근 가능

이제 다시 앞선 코드를 살펴보자

var a = 1;
function outer() {
  function inner() {
    console.log(a); // undefined
    var a = 3;
  }
  inner();
  console.log(a); // 1
}

outer();
console.log(a); // 1

전역 스코프에 a1로 존재하지만, inner 스코프는 현재 컨텍스트의 LexicalEnvironment부터 검색하기 때문에 undefined인 a를 반환한다.

변수은닉화, 함수 내부에서 변수를 선언했기 때문에 전역 공간에서 선언한 동일한 이름의 변수에 접근할 수 없음

전역변수와 지역변수

  • 전역변수: 전역 공간에서 선언한 변수
  • 지역변수: 함수 내부에서 선언한 변수

this

  • 실행 컨텍스트의 thisBinding에는 this로 지정된 객체가 저장
  • 실행 컨텍스트 활성화 당시에 this가 지정되지 않은 경우, this에는 전역 객체 저장

정리

  • 실행 컨텍스트: 실행할 코드에 제공할 환경 정보들을 모아놓은 객체
  • VariableEnvironment: 초기 상태 유지
  • LexicalEnvironment: 함수 실행 도중에 변경되는 사항 즉시 반영
  • environmentRecord: 매개변수명, 변수의 식별자, 선언한 함수의 함수명 등 수집
  • outerEnvironmentReference: 바로 직전 컨텍스트의 LexicalEnvironment 정보 참조
  • 호이스팅: environmentRecord의 수집 과정
  • 스코프: 변수의 유효범위
  • 스코프 체인: 안에서 밖으로 변수 찾기
  • 전역변수지역변수

참고자료

코어 자바스크립트

0개의 댓글