실행 컨텍스트

최형필·2021년 2월 2일
0

코어자바스크립트

목록 보기
2/6

https://media.vlpt.us/images/modolee/post/03e9931d-9d0a-4237-8357-a1a193cbdd88/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA%202020-09-27%20%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE%2010.46.12.png

실행 컨텍스트란


  • 실행 컨텍스트는 실행할 코드에 제공할 환경 정보들을 모아놓은 객체
  • 동일한 환경에 있는 코드들을 실행할 때 필요한 환경 정보들을 모아 컨텍스트 구성
  • 컨텍스트들을 순서대로 Call Stack에 쌓아 올림
  • 최상위 컨텍스트와 관련 있는 코드들을 실행
  • 전체 코드의 환경과 순서를 보장

실행 컨텍스트의 구성 방법

  • 전역 공간 → 자동 실행
  • eval() 함수 → 사용을 권장하지 않음
  • 함수 → 가장 흔한 실행 컨텍스트 구성 방법
  • 블록 → { } 로 둘러 쌓인 코드 내부. ES6 부터 지원

실행 컨텍스트와 콜스택

예제 코드

// ------------------- (1)
var a = 1;
function outer() {
  function inner() {
    console.log(a);
    var a = 3;
    // --------------- (2)
  }
  inner(); // -------- (3)
  console.log(a);
  // ----------------- (4)
}
outer(); // ---------- (5)
console.log(a);
// ------------------- (6)
  • 실행 순서 : (1) → (5) → (3) → (2) → (4) → (6)

콜스택 변화

https://media.vlpt.us/images/modolee/post/b8acdb24-e14d-4ed9-8a9c-7d9ca8de79ca/image.png

활성화 된 실행 컨텍스트의 수집 정보

  • VariableEnvironment
    • environmentRecord (snapshot)
    • outerEnvironmentReference (snapshot)
  • LexicalEnvironment
    • environmentRecord
    • outerEnvironmentReference
  • ThisBinding - this 식별자가 바라봐야 할 대상 객체

VariableEnvironment

  • 담기는 내용은 LexicalEnvironment와 같지만 최초 실행 시의 스냅샷을 유지
  • 실행 컨텍스트 생성 시 VariableEnvironment에 먼저 정보를 담고, 그대로 LexicalEnvironment에 복사 한 후 주로 LexicalEnvironment를 활용
  • 내부 구성 요소 : 현재 컨텍스트 내의 식별자들에 대한 정보 + 외부 환경 정보가 선언 시점의 스냅샷으로 저장
    • environmentRecord (snapshot)
    • outerEnvironmentReference (snapshot)

LexicalEnvironment

  • 내부 구성 요소 : VariableEnvironment와 동일하지만 변경 사항이 실시간으로 반영 됨
    • environmentRecord
    • outerEnvironmentReference

environmentRecord와 호이스팅(hoisting)

environmentRecord

  • 현재 컨텍스트와 관련 된 코드의 식별자 정보들이 저장
    • 컨텍스트를 구성하는 함수에 지정된 매개변수 식별자
    • 선언한 함수가 있을 경우 그 함수 자체
    • var로 선언 된 변수의 식별자
  • 컨텍스트 내부 전체를 처음부터 끝까지 쭉 훑어나가며 순서대로 수집
  • 전역 실행 컨텍스트
    • 변수 객체 생성 대신 자바스크립트 구동 환경이 별도로 제공하는 전역 객체를 활용
    • 브라우저의 window, Node.js의 global 객체 등
    • 이들은 내장(native) 객체가 아닌 호스트(host) 객체로 분류

호이스팅의 등장

  • 변수 정보를 수집하는 과정을 마쳤다면, 코드가 실행되기 전임에도 불구하고 자바스크립트 엔진은 이미 해당 환경에 속한 코드의 변수명들을 모두 알고 있게 됨
  • '자바스크립트 엔진은 식별자들을 최상단으로 끌어 올려 놓은 다음 실제 코드를 실행하라'라고 생각해도 코드 해석에 문제가 없음
  • 이러한 과정에서 호이스팅이라는 개념이 등장

호이스팅의 개념

  • 호이스팅(hoisting) : hoist (끌어 올리다) + ~ing → 식별자들을 최상단으로 끌어 올려 놓자
  • 변수 정보를 수집하는 과정을 더욱 이해하기 쉬운 방법으로 대체한 가상의 개념
  • 자바스크립트 엔진이 실제로 끌어 올리지는 않지만 편의상 끌어 올리는 것으로 간주하자는 것
  • 변수는 선언부와 할당부를 나눠 선언부만 끌어올리지만, 함수는 함수 전체를 끌어 올림
  • 호이스팅이 끝난 상태에서의 함수 선언문은 (*)과 같이 함수명으로 선언한 변수에 함수를 할당한 것처럼 여길 수 있음

함수 선언문과 함수 표현식

  • 함수 선언문 : 함수 정의부만 존재하고 별도의 할당 명령이 없는 것
    • 호이스팅 시 함수 전체를 끌어 올림
  • 함수 표현식 : 정의한 함수를 별도의 변수에 할당하는 것
    • 익명 함수 표현식 : 함수명을 정의하지 않음
    • 기명 함수 표현식 : 함수명을 정의함
      • 외부에서 함수명으로 호출 불가능
      • 내부에서 재귀함수를 호출하는 용도로 사용. 하지만 변수명으로도 호출 가능하여 굳이 쓸 필요는 없어 보임
      • 호이스팅 시 변수로 취급되어 선언 부분만 끌어 올림
function a() { /* ... */ } // 함수 선언문. 함수명 a가 곧 변수명
a(); // 실행 가능

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

var c = function d() { /* ... */ } // (기명) 함수 표현식. 변수명은 c, 함수명은 d
c(); // 실행 가능
d(); // 실행 불가능. 에러!
  • 함수 선언문이 코드 상단에 선언되어 있는 상태에서 동일한 이름의 함수 선언문이 하단에 중복되어 있을 경우 예기치 못한 동작이 발생할 우려가 있음

스코프, 스코프 체인, outerEnvironmentReference

스코프 체인

  • 현재 스코프에 선언 된 식별자이 없으면 상위 스코프로 이동하여 검색
  • 여러 스코프에서 동일한 식별자를 선언한 경우에는 무조건 스코프 체인 상에서 가장 먼저 발견된 식별자에만 접근 가능
  • 변수 은닉화 (Variable shadowing) : 상위 스코프에 선언되어 있지만, 현재 스코프에 이미 선언된 경우에는 값이 할당되어 있지 않다고 하더라도 현재 스코프의 변수를 우선으로 함
  • 예제
var a = 1;
var outer = function() {
  var inner = function() {
    console.log(a); // (1)
    var a = 3;
  };
  inner();
  console.log(a); // - (2)
}
outer();
console.log(a); // --- (3)
  • (1) inner 함수 컨텍스트에는 a 식별자가 존재하지만 아직 값이 할당되지 않았기 때문에 undefined 을 출력
  • (2) outer 함수 컨텍스트에는 a 식별자가 존재하지 않으므로, outerEnvironmentReference를 따라가서 전역 컨텍스트의 a에 들어 있는 1을 출력
  • (3) 전역 컨텍스트에는 a 식별자가 존재하고 값이 존재하므로 1 을 출력
profile
프론트엔드 개발자

0개의 댓글

관련 채용 정보