TIL.56 Core J.S - 2 실행 컨텍스트

Haiin·2021년 2월 22일
0

CoreJS

목록 보기
2/7
post-thumbnail

출저

  • 코어자바스크립트 - 정재남


1. 실행 컨텍스트란

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

동일한 환경에 있는 코드들을 실행할 때 필요한 환경 정보들을 모아 컨텍스트를 구성하고, 이를 콜 스택에 쌓아올렸다가, 가장 위에 쌓여있는 컨텍스트와 관련 있는 코드들을 실행하는 식으로 전체 코드의 환경과 순서를 보장한다.

동일한 환경이란 하나의 실행 컨텍스트를 구성할 수 있는 방법으로 전역공간, eval()함수, 함수 등이 있다. 보통 함수를 실행할 때 실행 컨텍스트를 구성한다고 생각하면 된다.

실행 컨텍스트와 콜 스택

// ------------------------------- (1)
let a = 1;
function outer() {
	function inner() {
    	console.log(a);
        let a = 3;
    }
    inner(); // ------------------ (2)
    console.log(a);
}
outer(); // ---------------------- (3)
console.log(a);
  1. 전역 컨텍스트 (js파일 열리는 순간 활성화) 콜스택에 담긴다.
  2. 계속 진행하다가 (3)에서 outer 함수 호출하면 자바스크립트 엔진이 outer에 대한 환경 정보를 수집해서 outer 실행 컨텍스트를 생성한 후 콜 스택에 담는다.
  3. 전역 컨텍스트와 관련된 코드의 실행을 일시중단, outer 실행 컨텍스트와 관련된 코드 (함수 내부 코드들) 을 순차로 실행한다.
  4. (2)에서 inner 함수의 실행 컨텍스트가 콜 스택의 가장 위에 담기면 outer 함수 실행을 멈추고 inner 함수 내부 코드들을 실행한다.
  5. inner 함수 내부에서 a 변수에 3을 할당하고 나면 inner 함수의 실행이 종료되어 실행 컨텍스트가 콜 스택에서 제거된다.
  6. 그러면 밑에 있던 중단된 outer 함수가 실행되고 (2) 다음부터 진행된다.
  7. 위와 같이 남은 전역 컨텍스트가 실행되고 종료되면 콜스택에서 제거되고 빈 콜스택만 남게 된다.


2. 실행컨텍스트 구성 요소

1. VariableEnvironment

2. LexicalEnvironment

3. ThisBinding



2-1. VariableEnvironment

현재 컨텍스트 내의 식별자들에 대한 정보 + 외부 환경 정보. 선언 시점의 LexicalEnvironment의 스냅샷으로, 변경 사항은 반영되지 않음.

environmentRecord + outer-EnvironmentReference
실행 컨텍스트를 생성할 때 VariableEnvironment에 정보를 먼저 담은 다음, 이를 그대로 복사해서 LexicalEnvironment를 만들고, 이후에는 LexicalEnvironment 를 주로 활용한다.

environmentRecord

현재 컨텍스트와 관련된 코드의 식별자 정보들 이 저장된다. 컨텍스트 내부 전체를 처음부터 끝까지 쭉 훑어나가며 순서대로 수집한다.
예를 들어, 함수자체, let, const로 선언된 변수의 식별자 등 을 수집하는데 이는 실행되기 전의 상태이고 자바스크립트 엔진이 이미 해당 환경에 속한 코드의 변수명들을 모두 알고 있게 되는 셈이다. 이렇게 식별자들을 최상단으로 끌어올려놓은 다음 실제 코드를 실행한다 라는 호이스팅이라는 개념과 동일하다고 봐도 무관하다.

function a (x) {
  console.log(x);
  let x;
  console.log(x);
  let x = 2;
  console.log(x);  
}
a(1)

인자를 함수 내부의 다른 코드보다 먼저 선언 및 할당이 이뤄진 것으로 간주 할 수 있다.

function a () {
  let x =1; // 수집 대상 1 (매개변수 선언)
  console.log(x); // (1)
  let x; // 수집 대상 2 (변수 선언)
  console.log(x); // (2)
  let x = 2; // 수집 대상 3 (변수 선언)
  console.log(x);  // (3)
}
a()

호이스팅 처리를 보기 쉽게 나열해 보기.

function a () {
  let x; //수집 대상 1의 변수 선언 부분
  let x; //수집 대상 2의 변수 선언 부분
  let x; //수집 대상 3의 변수 선언 부분
  
  x =1; //수집 대상 1의 할당 부분
  console.log(x); // (1)
  console.log(x); // (2)
  let x = 2; //수집 대상 3의 할당 부분
  console.log(x);  // (3)
}
a(1)

// (1), (2) 모두 1이 출력, (3) 에서는 2 가 출력

2-2. LexicalEnvironment

  • 처음에는 VariableEnvironment와 같지만 변경 사항이 실시간으로 반영됨.

2-2-1. 함수 선언문 과 함수 표현식

함수 선언문 (function declaration)

  • function 정의부만 존재하고 별도의 할당 명령이 없는 것 / 함수명 필수
function a () { } // a 가 함수명 이자 변수명
a()

함수 표현식 (function expression)

  • function 을 별도의 변수에 할당하는 것 / 기명 함수 표현식, 익명 함수 표현식
let b = function () { } // 익명 함수 표현식, b 가 함수명 이자 변수명
b()
let c = function d () { } // 기명 함수 표현식, 변수명은 c, 함수명은 d
c() // 실행 됨
d() // 실행 안됨 error

함수 선언문과 표현식의 호이스팅 차이점

console.log(sum(1, 2));
console.log(multiply(3, 4));

function sum (a, b) { // 함수 선언문 sum
  return a + b;
}

let multiply = function (a, b) { // 함수 표현식 multiply
  return a * b;
}

함수 선언문함수 표현식, 호이스팅을 마친 상태

function sum (a, b) { // 함수 선언문은 전체를 호이스팅
  return a + b;
}

let multiply; // 변수는 선언부만 끌어올린다

console.log(sum(1, 2));
console.log(multiply(3, 4));

multiply = function (a, b) { // 변수의 할당부는 원래 자리에 남겨둔다.
  return a * b;
}

위와 같이 함수 표현식변수의 할당부는 원래 자리에 남겨두는 함수 표현식의 특징으로 코드를 작성할때 안전한 방법이 될 수 있다.
반면에, 함수 선언문은 호이스팅되어 올라가면서 같은 이름의 함수는 덮어쓰기 때문에 앞서 선언한 함수를 사용할 수 없어 위험할 수 있다.



2-2-2. 스코프

  • 스코프란 식별자에 대한 유효범위. 자바스크립트는 전역공간을 제외하면 오직 함수에 의해서만 스코프가 생성.

outer-EnvironmentReference

현재 호출된 함수가 선언될 당시 의 LexicalEnvironment 를 참조한다.
선언될 시점은 과거에 콜 스택 상에서 어떤 실행 컨텍스트가 활성화된 상태일 때뿐이며 어떤 함수를 선언하는 행위 자체도 하나의 코드에 지나지 않으며, 모든 코드는 실행컨텍스트가 활성화 상태일 때 실행되기 때문이다.



2-3. ThisBinding

  • this에는 실행 컨텍스트를 활성화하는 당시에 지정된 this 가 저장된다.
  • ThisBinding 은 this 식별자가 바라봐야 할 대상 객체.


0개의 댓글