될때까지

((실행 컨텍스트)) 자바스크립트의 실행 컨텍스트, 호이스팅, TDZ, 스코프, 스코프 체이닝 본문

학습/JavaScript, TypeScript

((실행 컨텍스트)) 자바스크립트의 실행 컨텍스트, 호이스팅, TDZ, 스코프, 스코프 체이닝

랖니 2022. 9. 26. 20:29
728x90

자바스크립트 스터디 2번째 주제는 '실행 컨텍스트'다. 해당 개념은 파이썬을 공부할때도 접해본 적이 없었던 것 같은데.. 더욱 생소하게 다가왔다. 코어 자바스크립트 책을 읽기 전에, 생활코딩과 같은 여러개의 유튜브 영상을 시청하며 감을 잡고 있었는데 우아한 테크코스 테코톡에서 실행 컨텍스트 개념을 아주 잘 설명해줘서 해당 내용을 블로그에 정리해보려고 한다. => 하루의 실행 컨텍스트

 

🔥 자바스크립트엔진이 코드를 실행하는 방법

1. 자바스크립트 코드를 실행시키면  자바스크립트 엔진은 '콜 스택'이라는 통에 전역 실행컨텍스트를 담는다.
2. 실행 컨텍스트니까 Record와 Outer가 담겨있다.
3. 전역에서 함수 A를 호출하면 함수 A의 실행 컨텍스트를 생성하고 콜 스택에 담는다.
4. 함수 A에서 함수 B를 실행하면 또 함수 B의 실행 컨텍스트가 담긴다.
5. 함수 B의 실행을 마치고 함수 B가 종료되면 함수B의 실행 컨텍스트가 사라지고 그렇게 최상단의 컨텍스트 부터 콜 스택에서 나간다.

1. Record로 JS 호이스팅 이해하기

var TVChannel = 'Netflix';

console.log(TVChannel);

var를 사용해서 변수를 선언하고 Netflix를 할당했다. 아랫줄에서 콘솔에 이를 찍어보면, 예상대로 Netflix가 콘솔에 찍힌다. 
그렇다면 선언 라인 위에서 콘솔을 찍으면 어떻게 될까?

console.log(TVChannel); // ?

var TVChannel = "Netflix";

선언도 하기 전인데 해당 변수를 어떻게 찾니, 에러가 발생할 것 같다고 생각했는데 undefined가 찍혔다.

 

호이스팅

선언 라인 전에도 에러가 나지 않고 변수를 참조할 수 있는 현상을 '호이스팅(Hoisting)'이라고 한다.
=> 선언문이 마치 최상단에 끌어올려진 듯한 현상

호이스팅이 발생하는 이유는 자바스크립트 엔진이 전체 코드를 스캔하면서 변수같은 정보를 실행 컨텍스트 어딘가에 미리 기록해놓기 때문이다. 이때 기록해두는 곳이 Environment Record(환경 레코드 - 식별자와 식별자에 바인딩된 값을 기록)다.

호이스팅에는 변수 호이스팅, 함수 호이스팅이 있다.

1-1) 변수 호이스팅

var

1.자바스크립트 엔진은 코드를 실행하면 우선 전역 실행 컨텍스트 한 칸을 생성해서 콜 스택에 넣는다.
2.전체 코드를 스캔하면서 선언할 게 있는 지 찾아보고 있다면 먼저 선언한다 -> TVChannel
3.해당 TVChannel은 var 키워드로 선언했기 때문에 undefined로 값을 초기화해둔다.
------------------------------------------여기까지를 생성단계(Creation Phase)
실행 컨텍스트를 생성하고, 선언문만 실행해서 Environment Record에 기록해두는 단계

4.코드의 1번째 줄 콘솔로그를 실행하면서 TVChannel의 값인 undefined를 출력한다.
5.코드의 2번째 줄을 실행하면서 TVChannel에 바인딩 된 값을 "Netflix"로 업데이트해서 기록한다.
6.마지막 줄을 실행하면서 Netflix를 출력한다.
----------------------------------------------------여기까지를 실행단계(Execution Phase)
선언문 외 나머지 코드를 순차적으로 실행해서 Environment Record에 참조하거나 업데이트하는 단계

➡️ var키워드를 사용하면 선언과 초기화가 동시에 이뤄진다.

const, let

console.log(TVChannel);   // Reference Error

const TVChannel = 'Netflix';

console.log(TVChannel);

const나 let로 변수를 선언하면 TVChannel 식별자를 저장하긴 하지만 값을 초기화하지 않는다. 

선언문 이전에 참조하고 있기 때문에 Reference Error가 발생한다.
이처럼 선언 라인 이전에 식별자를 참조할 수 없는 구역을 일시적 사각지대(Temporal Dead Zone : TDZ)라고 한다. 

➡️ const, let키워드로 선언하면 undefined로 값을 초기화하지 않기 때문에 할당문 직전까지는 아무런 값이 담기지 않는다.

 

1-2) 함수 호이스팅

함수표현식

var 키워드를 사용해서 함수를 선언하고, 선언문 이전에 실행하려고 하면 

study();

var study = () => {
	console.log('공부하세요')
}

 

환경 레코드에 기록되어있는 study이 값은 undefined다.
undefined는 함수와 달리 호출 ();을 할 수 없기 때문에 Type Error가 발생한다.

같은 함수를 const 키워드를 사용해서 선언하고, 선언문 전에 실행하면,

환경 레코드에 기록된 값이 없어서 Reference Error가 발생한다.

변수에 함수를 담아서 함수를 선언하는 방식을 함수 표현식(Function Expression)이라고 하는데 변수 호이스팅과 동일하게 동작한다. 

 

함수 선언문

function키워드로 함수를 선언하면

study();

function study() {
	console.log('공부합시다');
}

자바스크립트 엔진이 완성된 함수 객체를 생성해서 환경 레코드에 기록해둔다. 
study함수를 실행하면 study함수가 에러없이 실행된다. 

함수 선언문은 선언과 동시에 함수가 생성되서 환경 레코드에 기록되기 때문에 선언 전에도 함수를 사용할 수 있다.

 

정리

  • var를 사용해서 함수를 생성하면 undefined가 자동 할당되어 TypeError을 반환
  • let, const를 사용해서 함수를 생성하면 초기화된 값이 없기 때문에 Reference Error반환
  • 함수 선언문으로 함수를 선언하면 선언 라인 전에도 함수 호출 가능

 

2. Outer로 JS 스코프체이닝 이해하기

Outer

Outer Environment Reference : 외부 환경 참조 -> 바깥 Lexical Environment를 가리킨다.

 

 

  1. 함수선언문으로 goTo2F() 함수를 생성했다. 함수 선언문은 선언하는 동시에 환경 레코드에 함수가 기록된다.
  2. 해당 함수를 실행하면서 goTo2F() 새로운 실행 컨텍스트가 생성된다.
  3. 그리고 goTo2F()안에 있는 lamp를 기록해야하는데
  4. 환경레코드에 불이 꺼진 램프/ 불이 켜진 램프 2개가 있는데 어떤 값을 가져와야할까?
    코드에서 변수나 함수의 값을 결정하는 것을 식별자 결정(Identifier Resolution)이라고 한다.
  5. 콜 스택 안에 동일한 식별자가 여럿일때 자바스크립트 엔진은 어떻게 outer를 활용해서 의사결정을 할까?

  1. 먼저 현재 활성화된(최상단) 실행 컨텍스트의 환경 레코드를 먼저 살펴본다.
  2. 값이 있다면 출력하면 된다. 없는 값을 찾으면 어떻게 할까?
  3. 먼저 현재 활성화된 실행 컨텍스트의 환경 레코드안에 있는지 살펴본다. 근데도 없다.
  4. 자바스크립트 엔진은 outer가 가리키는 바깥 렉시컬 환경으로 가서 값을 찾는다.
  5. 여기도 없다면 또 outer를 타고 바깥 렉시컬 환경으로 이동한다.
  6. 전역 실행 컨텍스트의 렉시컬 환경까지 왔는데도 값이 없다.
  7. 전역 실행 컨텍스트는 최상위 실행 컨텍스트이기 때문에 값이 없다는 결론을 내리고 Reference Error를 반환한다.

만약 찾고자 하는 값을 outer가 가리키는 바깥 렉시컬 환경에서 찾았다면 더이상의 탐색을 종료하고 해당 값을 반환한다.
(outer를 타고 더 아래 -하얀색 동그라미-로 찾으러 가지 않는다는 이야기)

이 때 1층과 2층의 램프, 즉 식별자가 같기 때문에 상위 스코프에 선언된 식별자의 값이 가려지게 되는 현상을 변수 섀도잉이라고 한다.

 현재 활성화된 실행 컨텍스트는 오직 하나이지만 이전 렉시컬 환경을 가리키는 outer로 타고 타고 찾을 수 있다.
이렇게 식별자를 결정할 때 활용하는 스코프들의 연결리스트를 스코프 체인이라고 하고 
식별자를 결정하기 위해 타고 타고 가서 찾는 과정 자체를 스코프 체이닝이라고 한다.

 

3. Execution Context 정리

실행 컨텍스트는 코드를 실행하는 데 필요한 환경을 제공하는 객체다.

여기서 환경은 코드 실행에 영향을 주는 조건이나 상태를 의미한다.

즉, 코드를 실행하는 데 필요한 조건이나 상태를 모아둔 객체가 실행 컨텍스트다. 보다 효율적인 식별자 결정을 위해 필요한 수단이다.

 

728x90