코어 자바스크립트 2장: 실행 컨텍스트

송나은·2021년 6월 4일

JavaScript

목록 보기
18/23

실행 컨텍스트

실행할 코드에 제공할 환경 정보들을 모아놓은 객체.

동일한 환경에 있는 코드들을 실행할 때 필요한 환경정보들을 모아 컨텍스트를 구성하고, 이를 콜스택에 쌓아올렸다가, 가장 위에 쌓여있는 컨텍스트와 관련 있는 코드를 실행한다. 실행이 완료되면 콜스택에서 제거된다.

자바스크립트 파일이 열리는 순간, 전역 컨텍스트가 활성화된다.

실행 컨텍스트가 활성화 되는 시점에 하는 3가지 동작

  • 호이스팅 (선언된 변수를 위로 끌어올린다)
  • 외부 환경정보를 구성한다. (VariableEnvironment, LexicalEnvironment, ThisBinding)
  • This 값을 설정한다.

실행 컨텍스트의 thisBinding에는 this로 지정된 객체가 혹은 전역 객체가 저장된다.

스택과 큐 (+ 덱)

  • 큐: 양쪽이 모두 열려있는 구조. 한쪽은 입력만, 다른 한쪽은 출력만 담당한다. First In First Out.
  • 스택: 출입구가 하나뿐인 깊은 우물 같은 데이터 구조. Last In First Out. push(), pop()

🦊 Stackoverflow 스택의 크기 이상의 자료를 push 하려고 할 때의 오류

  • 덱: Double Ended Queue. 입력과 출력을 양쪽 끝에서 가능하게 한다.

VariableEnvironment

실행 컨텍스트를 생성할 때 현재 컨텍스트 내의 식별자들에 대한 정보 + 외부 환경 정보를 담는다.

선언 시점 LexicalEnvironment의 스냅샷으로 초기 상태를 유지한다.

LexicalEnvironment

VariableEnvironment에 담긴 정보를 복사한다.

함수 실행 도중 변경되는 사항이 실시간으로 반영된다.

EnvironmentRecord

매개변수명, 변수의 식별자, 선언한 함수의 함수명 등 현재 컨텍스트와 관련된 코드의 식별자 정보를 수집한다. (→ 호이스팅)

전역 실행컨텍스트는 자바스크립트 구동 환경이 별도로 제공하는 객체(전역객체)를 활용한다.

  • 전역객체 (Global object): 브라우저의 window, Node.js의 global 객체

호이스팅

코드가 실행되기 전에 변수를 수집하는 과정 (=식별자들을 최상단으로 끌어올린다)

  • 호이스팅 규칙: 변수는 선언부만 끌어올리는 반면 함수 선언은 함수 전체를 끌어올린다.
// 원본
function a () {
  console.log(b);
  var b = 'bbb';
  console.log(b);
  function b () {}
  console.log(b);
}

a();
// 호이스팅
function a () {
  var b;
  function b () {
    console.log(b);
    b = 'bbb';
    console.log(b);
    console.log(b);
  }
}
  
a();
// 함수 표현식
function a () {
  var b;
  var b = function b () {
    console.log(b);
    b = 'bbb';
    console.log(b);
    console.log(b);
  }
}

a();
  • Rest Parameter: 유사배열 객체인 arguments를 배열처럼 활용하기 위해 ES6에 추가된 것.
  • Override 동일한 변수명에 서로 다른 값을 할당할 경우, 나중에 할당한 값이 덮어 씌운다.

함수 선언문과 함수 표현식

  • 함수 선언문: function의 정의부만 존재하고 별도의 할당 명령이 없다. 반드시 함수명이 정의돼 있어야 한다(기명 함수 표현식).
  • 함수 표현식: 정의한 function을 별도의 변수에 할당하는 것이다.
// 함수를 정의하는 세 가지 방식
function a () {} // 함수 선언문. 함수명이 곧 변수명.
var b = function () {} // (익명) 함수 표현식. 변수명이 곧 함수명(= 함수의 name 프로퍼티에 할당). 
var c = function d () {} // 기명 함수 표현식 -> d는 굳이..필요없는 함수명

a(); // 실행
b(); // 실행
c(); // 실행
d(); // error

스코프, 스코프체인

스코프

식별자에 대한 유효범위

  • ES5까지에서는 전역공간을 제외하면 오직 함수에 의해서만 스코프가 생성된다.
  • ES6에서부터는 블록에 의해서도 스코프가 생성된다. (let, const, class, strict mode에서 함수선언)

var 함수 스코프. 식별자의 유효범위: 함수

function loop() {
  for(var i = 0; i < 5; i++) {
    console.log(i);
  }
  console.log(i);
}
loop();

/* 
0
1
2
3
4
5
*/

let 블록 스코프. 식별자의 유효범위: for문

function loop() {
  for(let i = 0; i < 5; i++) {
    console.log(i);
  }
  console.log(i);
}
loop();

/* 
0
1
2
3
4
ReferenceError: i is not defined
*/

TDZ(Temporal Dead Zone).

let과 const도 호이스팅이 되지만 TDZ에 의해 에러가 발생한다.
변수의 선언 단계와 초기화 단계 사이에 일시적 사각지대(TDZ)가 존재한다.

  • 변수생명주기
  1. 선언: 변수를 실행 컨텍스트의 변수 객체에 등록하는 단계.
  2. 초기화: 실행 컨텍스트에 존재하는 변수 객체에 선언단계의 변수를 위한 메모리를 만드는 단계.
  3. 할당: 사용자가 초기화된 메모리의 다른 값을 할당하는 단계.

스코프 체인

식별자의 유효범위를 안에서부터 바깥으로 차례로 검색해 나가는 것.

  • Outer-EnvironmentReference: 현재 호출된 함수가 '선언될 당시'(바로 직전 컨텍스트)의 LexicalEnvironment를 참조한다. 스코프 체인 상에서 가장 먼저 발견된 식별자에만 접근 가능하다.
var a = 1;
var outer = function () {
  var inner = function () {
    console.log(a);
    var a = 3;
  }
  
  inner();
  console.log(a);
};

outer();
console.log(a)

스코프체인 과정

  1. 전역 컨텍스트가 활성화 되어 외부환경정보를 구성한다. - LexicalEnvironment, VariableEnvironment, thisBinding
  2. 전역 EnvironmentRecord에 식별자 a와 outer를 저장한다. (전역변수)
  3. a에 1, outer에 함수를 할당한다.
  4. outer 함수를 실행한다. outer 실행 컨텍스트가 활성화되고, EnvironmentRecord에 식별자 inner를 저장한다. (지역변수)
  5. outer 스코프에 있는 inner에 함수를 할당한다.
  6. inner의 LexicalEnvironment에서 a를 탐색하고, undefined를 출력한다.
  7. inner 스코프에 있는 변수 a에 3을 할당한다. (지역변수)
  8. inner 함수가 종료되어 inner 실행 컨텍스트가 콜스택에서 제거된다.
  9. outer 실행 컨텍스트가 재활성화 된다.
  10. outer의 LexicalEnvironment에서 a를 탐색하고, 1을 출력한다.
  11. outer 함수가 종료되어 outer 실행 컨텍스트가 콜스택에서 제거된다.
  12. 전역 컨텍스트가 재활성화 된다.
  13. 전역 컨텍스트의 LexicalEnvironment에서 a를 탐색하고, 1을 출력한다.
  14. 전역 컨텍스트가 콜스택에서 제거되고 종료한다.

콘솔에서 스코프체인 확인하는 방법

  1. 함수 내부에서 함수를 출력한다. console.dir(inner)
    → 실제로 호출할 외부 변수들의 정보만 보여준다.
  2. 함수 내부에서 debugger

전역변수

전역 컨텍스트의 LexicalEnvironment에 담긴 변수

Reference

profile
그때그때 공부한 내용과 생각을 기록하는 블로그입니다.

0개의 댓글