호이스팅, 스코프, 클로저, 실행 컨텍스트

kim unknown·2022년 8월 29일
0

기술면접 대비

목록 보기
1/5
post-thumbnail

1. 호이스팅

호이스팅(Hoisting)은 변수 선언문이 마치 호이스팅 최상단에 끌어올려진 듯한 현상이다. 실제로 선언문이 있는 코드라인을 물리적으로 최상단으로 끌어올린 것이 아니라, 자바스크립트 엔진이 먼저 코드 전체를 스캔하면서 변수를 실행 컨텍스트에 미리 기록해두기 때문에 발생하는 것이다.

var, let, const 모두 호이스팅이 발생한다. 하지만 변수 생성 과정의 차이로 인해 값이 할당되기 전에 참조하면 서로 다른 결과를 도출한다.

변수의 생성 단계는 3가지로 나뉜다.
1. 선언 단계
2. 초기화 단계
3. 할당 단계

var는 선언과 초기화가 동시에 진행된다. 이 때 값을 undefined로 초기화하기 때문에 값을 할당하기 전에 참조해도 오류가 나지 않고 undefined 값을 얻는다.

반면 letconst는 선언 단계와 초기화 단계가 분리되어 진행된다. 호이스팅 되면서 선언단계가 이루어지지만, 초기화 단계는 실제 코드에 도달했을 때 진행된다. 따라서, 실제 코드에 도달하기 전에 먼저 참조를 하게 되면 ReferenceError가 발생한다.

이는 Temporary Dead Zone(TDZ) 때문이다. let과 const로 선언된 변수들은 실제 코드에 도달하기 전까지는 TDZ 영역에 존재하며, 접근할 수 없다. TDZ로 인해 잠재적인 버그를 줄일 수 있다.

* 변수 선언 코드에 도달하기 전까지의 영역을 변수에 접근할 수 없다는 의미로 Temporary Dead Zone(TDZ)이라고 한다.

함수 표현식(const func = () => {})은 함수를 변수에 담고 있기 때문에 변수 호이스팅과 동일하게 동작한다.

함수 선언문(function func() {})은 실행 컨텍스트에 함수 전체가 통채로 저장되기 때문에 함수 이름을 key로 하고 함수 자체를 value로 저장하여 완전하게 초기화된다. 따라서, 완전하게 저장된 상태에서 접근하는 것이기 때문에 변수 선언 이전에 변수에 접근하더라도 변수를 참조할 수 있다.

요약

호이스팅은 변수 선언문이 마치 호이스팅 최상단에 끌어올려진 듯한 현상이다.
var로 선언된 변수는 선언과 초기화가 동시에 진행된다. 값을 할당하기 전에 참조해도 오류가 나지 않고 undefined 값을 얻는다.
let과 const로 선언된 변수는 선언과 초기화가 분리되어 진행된다. 실제 코드에 도달하기 전까지는 TDZ 영역에 존재하며, 접근할 수 없기 때문에 ReferenceError가 발생한다.


2. 스코프

스코프는 변수의 접근 가능 유효범위로 변수 이름, 함수 이름과 같은 식별자가 선언된 위치에 따라 다른 코드에서 참조 가능 여부가 결정되는 것이다.

전역적으로 선언된 변수는 전역 스코프에, 지역적으로 선언된 변수는 지역 스코프에 있다.
전역스코프와 지역스코프는 서로 계층적으로 연결되어 있는 데, 이것을 스코프 체인이라 한다. 스코프 체인은 물리적으로 존재하며 자바스크립트 엔진은 이 스코프 체인을 통해 변수를 참조한다.

스코프 체인은 무조건 상위(지역->전역) 스코프로만 올라가면서 참조한다. 자신의 스코프에서 변수를 찾고 해당 변수가 없다면, 상위 스코프로 타고 타고 올라가면서 변수를 찾는다. 이 과정에서 변수를 찾으면 반환하고, 가장 상위인 전역 스코프까지 와서도 끝내 못 찾는다면 ReferenceError를 반환한다.

이렇게 계층적으로 연결되어 있는 스코프 체인 덕분에 하위 스코프에서 상위 스코프에 있는 변수를 참조할 수 있는 것이다.

*생명 주기를 마감한 상위 함수의 변수를 참조할 수 있는 이유 -> 클로저

스코프체인 참조 과정
1. fooColor를 출력하려할 때 bar 스코프에는 fooColor가 존재하지 않음.
2. 스코프 체인을 타고 foo 스코프로 이동하여 변수를 찾아내고 출력함.
3. 마찬가지로 globalColor를 출력하려할 때 bar 스코프에는 fooColor가 존재하지 않음
4. 스코프 체인을 타고 foo 스코프로 이동하여 변수를 찾음. 하지만, foo 스코프에도 존재하지 않음.
5. global 스코프로 이동하여 변수를 찾아내고 출력함.

요약

스코프는 변수의 접근 가능 유효범위이며, 상위 스코프와 하위 스코프들이 계층적으로 연결되어 있는 것을 스코프 체인이라고 한다. 이 때문에 하위 스코프에서 상위 스코프에 있는 변수를 참조할 수 있는 것이다.


3. 클로저

클로저는 함수와 그 함수의 렉시컬 환경의 조합이다. 클로저의 핵심은 스코프를 이용해서, 변수의 접근 범위를 지정하는 것이다.

클로저를 사용하면 스코프에 데이터를 보존하기 때문에 외부 함수의 실행이 끝나더라도 외부 함수 스코프에서 선언된 변수에 접근이 가능하다.
또한, 정보의 접근을 제한할 수 있다.
클로저 함수를 변수에 할당하면 각자 독립적으로 값을 사용하고 보존할 수 있기 때문에 모듈화에 유리해진다.

요약

클로저는 함수와 그 함수의 렉시컬 환경의 조합이다. 클로저의 핵심은 스코프를 이용해서, 변수의 접근 범위를 지정하는 것이다. 클로저를 사용하면 데이터 보존이 가능하고 정보의 접근을 제한할 수 있으며, 모듈화에 유리해진다.


4. 실행 컨텍스트

실행 컨텍스트는 코드를 실행하는 데 필요한 환경(조건이나 상태)을 제공하는 객체이며, 식별자를 더욱 효율적으로 결정하기 위한 수단이 된다.

실행 컨텍스트는 Variable Environment, Lexical Environment, ThisBinding을 구성 요소로 가진다.

  • VariableEnvironment : 현재 컨텍스트 내의 식별자들에 대한 정보 + 외부 환경 정보. 선언 시점의 LexicalEnvironment의 스냅샷으로, 변경 사항은 반영되지 않음
  • LexicalEnvironment : 처음에는 VariableEnvironment와 같지만 변경 사항이 실시간으로 반영됨.
  • ThisBinding : this 식별자가 바라봐야 할 대상 객체

실행 컨텍스트는 동일한 환경에 있는 코드들을 실행할 때 필요한 환경 정보들을 모아 객체를 구성하고, 이를 콜 스택에 쌓아올렸다가, 가장 위에 쌓여있는 컨텍스트와 관련 있는 코드들을 실행한다. 이렇게 해서 전체 코드의 환경과 순서를 보장할 수 있다. 어떤 실행 컨텍스트가 활성화되는 시점에 선언된 변수를 위로 끌어올리고 외부 환경 정보를 구성하고, this 값을 설정하는 등의 동작을 수행한다.

요약

실행 컨텍스트는 코드를 실행하는 데 필요한 환경(조건이나 상태)을 제공하는 객체이며, 식별자를 더욱 효율적으로 결정하기 위한 수단이다. 실행 컨텍스트로 전체 코드의 환경과 순서를 보장할 수 있다.


참고 자료
📑 [JavaScript] 클로저(Closures)란 무엇일까?
📑 [10분 테코톡] 💙 하루의 실행 컨텍스트

0개의 댓글