코어 자바스크립트(실행 컨텍스트)

L·2022년 11월 2일
0

코어자바스크립트

목록 보기
2/6
post-thumbnail

실행 컨텍스트

실행할 코드에 제공할 조건과 환경 정보들(현재 환경과 관련된 식별자 정보)을 모아놓은 객체.

실행컨텍스트가 활성화될 시점에 선언된 변수를 끌어올리고(호이스팅), 환경정보 설정과 this가 설정되는 등의 동작이 일어남.
동일한 환경에 있는 코드들을 실행할때 필요한 정보를 모아서 컨텍스트를 구성하여 이를 콜 스택에 올리고, 가장위에 있는 컨텍스트와 관련 코드를 먼저 실행하는 식으로 진행이 됨(스택과 똑같은 개념 FILO).
실행컨텍스트 구성 방법은 전역공간, eval()함수, 함수,블록({})(ES6)등이 있으며, 일반적인 실행컨텍스트 구성은 함수를 실행하는 방법뿐임.

  • 실행 컨텍스트 소스 코드
var a = 1;
function outer(){
  function inner(){
    console.log(a);
    var a = 3;
  }
  inner();
  console.log(a);
}
outer();
console.log(a);

콜스택 순서
1 . 자바스크립트를 실행시키는 순간, 빈 콜스택에 전역 컨텍스트가 담김.
2 . 순차적으로 진행이 되다가 outer() 함수가 호출되면, 콜스택에 outer 실행 컨텍스트가 쌓임.
3 . outer 함수 내부코드가 실행하하다가 inner()함수가 호출되면, 콜스택에 inner 실행 컨텍스트가 쌓임.
4 .inner함수 내부코드 실행이 끝나면, 콜스택에 inner()의 실행 컨텍스트가 콜 스택에서 제거.
5 .inner함수 실행 컨텍스트가 제거가 되고, 콘솔출력까지 끝나면, 콜스택에 outer()의 실행 컨텍스트가 콜 스택에서 제거.
6 . 콜 스택에 남은 전역 컨텍스트에 있는 콘솔 출력까지 끝나면, 콜 스택에 전역 컨텍스트가 제거되면서, 콜 스택에는 아무것도 없는상태로 종료.

  • 실행 컨텍스트에 담긴 정보
    1. VariableEnvironment

      현재 컨텍스트 내의 식별자들에 대한 정보(environmentRecord) + 외부 환경 정보(outerEnvironmentReference) 를 말하며 LexicalEnvironment의 스냅샷으로 변경되지 않음.

    2. LexicalEnvironment

      VariableEnvironment와 같은정보가 최초로 들어가지만, 변경사항이 실시간으로 반영되는 정보.

    3. ThisBinding

      this 식별자가 바라봐야 할 대상 객체

LexicalEnvironment

한국어 번역으로 '어휘적 환경','정적 환경'이라는 단어로 많이 해석.
여기서 사용자는 사전적인이라는 표현이 더 어울린다고 언급함.
예를 들어 "컨텍스트 내부에 a,b,c같은 식별자들이 있고 외부 정보는 d를 참조하도록 구성되어있다" 이런식으로 컨텍스트를 구성하는 환경정보가 있는 사전처럼 구성했다로 이해.(인프런 코어 자바스크립트 강의 참고)

environmentRecord와 호이스팅

1.environmentRecord가 가지고 있는 정보

  • 현재 컨텍스트와 관련된 식별자 정보가 저장. 아래 3가지의 정보가 들어가있으며, 이를 컨텍스트 내부 전체를 끝까지 순서대로 수집.

    1.함수에 지정된 매개변수 식별자
    2.선언한 함수가 있을경우 함수 그 자체 정보.
    3.var로 선언된 변수의 식별자

2.호이스팅(Hoisting)

  • 자바 스크립트 엔진이 소스 코드의 environmentRecord 정보를 수집. 코드를 실행하기전에는 해당 환경의 코드 식별자들을 전부 알고있는 상황. 이 때, 자바스크립트 엔진은 실행컨텍스트 실행 시, 모든 식별자 정보를 알기때문에, 실행하는 소스코드 상 아래에 있는 실행컨텍스트가 실행이 가능하다. 이 때, 식별자 정보는 실제로 실행컨텍스트 맨위로 끌어올려지지않지만 편의상 끌어 올리는 것으로 간주. 즉 Hoisting이 발생.

    function a(){
    console.log(func());
    function func(){
      return 1000;
    }
    var x = 1;
    console.log(x);
    var x;
    console.log(x);
    var x = 2;
    console.log(x);
    }
    a();

    위 소스 코드에서 a함수를 실행하면 콜스택에 a 함수에 관련된 실행 컨텍스트가 실행. 이 때, 식별자 정보는 가상의 Hoisting 현상에 의해 a 함수 내부 위로 끌어올려져서, 아래와 같은 소스로 실행이 됨.

    function a(){
     function func(){
       return 1000;
     }
     console.log(func());
     var x;
     var x;
     var x;
     
     x = 1;
     console.log(x);
     console.log(x);
     
     x = 2;
     console.log(x);
    }
    a();

    1.func함수 선언
    2.func함수 실행 결과값 출력
    3.변수 x를 선언.
    4.아래에도 식별자 x를 선언하지만, 이미 할당 되어있기때문에 무시.
    5.변수 x에 데이터 1를 할당.
    6.11,12번째줄에는 할당된 변수 x의 데이터 값 출력.(1)
    7.14번째줄에는 할당된 변수 x에 데이터 2를 할당.
    8.15번째줄에 할당된 변수 x의 데이터 값 출력.(2)
    9.a함수의 컨텍스트가 종료되서 콜 스택에서 제거. 그 다음 전역컨텍스트도 종료되어 콜 스택에서 제거

처음에는 undefined,1,undefined,2순서로 출력이 되는줄 알았지만, 이전에 공부했었던 DataType의 식별자 할당하는 방법을 생각하면 이미 식별자 x가 할당이 되어있기때문에, 아래에 할당외어있는 두번째에 재선언은 무시한다고 생각 하면 될꺼 같다.

3.함수 선언문과 함수 표현식

  • 둘다 함수를 정의하는데 사용하는 방식
  • 함수 선언문 : function 정의부만 존재. 함수명 자체가 곧 변수명.(필수)
  • 함수 표현식 : 정의한 함수를 별도의 변수에 할당. 함수명을 선언해도 되고(기명 함수 표현식) ,안해도 상관없음.(익명 함수 표현식) 선언부가 맨위로 끌어올라오고, 일반 변수 값 할당 처럼 함수를 할당하는 곳은 그대로 남아있는건 똑같음.

스코프, 스코프 체인, outerEnvironmentReference

Scope는 식별자에 대한 유효범위.

  • ES5까지의 자바스크립트는 전역공간을 제외하고, 함수범위의 스코프가 생성됨.(var)(ES6에서 let,const는 블록 범위)

스코프체인

outerEnvironmentReference: 현재 호출된 함수가 선언될 당시의 외부 환경(LexicalEnvironment)를 참조.
스코프 체인: 식별자의 유효범위 안에서 바깥으로 차례로 검색해 나가는것을 말함.

  • 스코프 체인 예제 1
var a = 1;
var outer = function(){
    var inner = function(){
        console.log(a);
    }
    inner();
}
outer();

a변수값을 찾는과정
1.inner 함수의 LexicalEnvironment에는 변수a가 없기때문에 outerEnvironmentReference(= outer함수의 LexicalEnvironment) 참조.
2. inner함수의 outerEnvironmentReference 에도 변수 a는 없기때문에, outer 실행컨텍스트의 outerEnvironmentReference(=전역컨텍스트의 LexicalEnvironment) 참조.
3. 전역 컨텍스트의 LexicalEnvironment에는 변수 a가 있기때문에, 값 1이 출력이 됨.

  • outerEnvironmentRefence의 존재때문에 스코프 체인이 발생.
  • 만약 여러 스코프에서 동일한 식별자를 선언한 경우 스코프 체인 상에서 가장 먼저 발견된 식별자에만 접근이 가능.(예제에서 outerLexicalEnvironment에 동일한 식별자가 있었다면, 그 식별자의 값을 찍음)
var a = 1;
var outer = function(){
    var inner = function(){
        console.log(a);
        var a = 3;
    }
    inner();
    console.log(a);
}
outer();
console.log(a);

스코프 체인 과정.
1. 전역컨텍스트 활성화.environmentRecord에는 {a,outer} 식별자 저장하고 값 1과 함수 표현식을 할당. 이 때 outerEnvironmentReference에는 아무것도 담기지 않음.
2.outer함수 호출. outer실행 컨텍스트가 활성화.
3. outer의 실행 컨텍스트의 environmentRecord에는 {inner}식별자를 저장하고 함수 표현식을 할당. 이 때 outerEnvironmentReference는 전역 컨텍스트의 LexicalEnvironment가 됨.
4. inner함수 호출. inner실행 컨텍스트가 활성화.
5.inner의 실행 컨텍스트의 environmentRecord에는 {a}식별자를 저장. 이 때 outerEnvironmentReferenceouter함수의 LexicalEnvironment가 됨.
6. a값을 출력하려고하지만, 호이스팅에 의해 식별자는 선언만 되어있고 값은 할당 되지않았기때문에 undefined가 나옴.
7. inner 함수호출이 종료면서 콜스택에서 제거. a값을 출력함. outer 함수의 LexicalEnvironment에는 변수 a가 없기때문에, outerEnvironmentReference(=전역 컨텍스트 Lexical Environment)를 참조. 변수a를 찾은결과 변수가 있기때문에 1을 출력.
8. outer 함수호출이 종료면서 콜스택에서 제거. a값을 출력함. 전역컨텍스트의 LexicalEnvironment에는 변수 a가 없기때문에, 1을 출력.
9. 전역 컨텍스트에서의 작업이 종료되면서 콜스택에서 제거되고 종료.


정리

  1. 실행 컨텍스트는 실행할 코드의 정보와 실행될 식별자 정보를 모아둔 객체 이며, 전역 공간에서 생성되는 전역 컨텍스트, eval함수 실행으로 생기는 컨텍스트, 함수 컨텍스트와 {}블럭 컨텍스트가 있음.
  2. 실행 컨텍스트는 VariableEnvironment, LexicalEnvironment, this Binding으로 구성.
  3. VariableEnvironment, LexicalEnvironment는 최초에 EnvironmentRecord(변수 식별자, 함수 선언문, 매개변수 식별자)와 outerEnvironmentReference(외부 환경 정보 = 상위 Scope의 LexicalEnvrionment)가 최초로 똑같이 생성이 되지만 VariableEnvironment는 해당 함수의 실행컨텍스트 최초 스냅샷 값이고, LexicalEnvironment는 함수 실행 도중에 변경되는 사항이 즉시 반영 되는 차이점이 있음.
  4. 호이스팅은 실행 컨텍스트안에 있는 식별자가 가상을 끌어올리는것처럼 보이는 가상의 현상으로써 실행하는 소스코드 상 아래에 있는 실행컨텍스트가 실행이 가능하다.
  5. Scope는 변수의 유효범위.
  6. 스코프 체인이란 식별자의 유효범위 안에 값이 없으면 outerEnvironmentReference를 이용하여 바깥방향으로 차례로 검색해 나가는것을 말함.민약에 전역 컨텍스트까지 값이 없다면, undefined를 리턴.(=식별자의 유효범위 안에서 바깥으로 차례로 검색해 나가는것)

0개의 댓글