1. 실행컨텍스트란?
실행컨텍스트는 실행할 코드에 제공할 환경정보를 모아놓은 객체로, 자바스크립트는 실행컨텍스트가 활성화되는 시점에 선언된 변수를 호이스팅하고, 외부환경정보를 구성하고, this값을 설정하는 등의 동작을 수행하게된다. 자바스크립트는 동일한 환경에 있는 코드들을 실행할때 필요한 환경정보들을 모아 컨텍스트를 구성하고, 이를 콜스택에 쌓아올렸다가 가장 위에서부터 실행하여 전체코드의 환경과 순서를 보정하게 된다. 어떤 실행컨텍스트가 활성화될때, 자바스크립트 엔진은 해당 컨텍스트에 관련된 코드들을 실행하는데 필요한 환경정보를 수집해서 실행컨텍스트 객체에 저장하게되는데, 이때 수집하는 정보는 variavle environment, lexical environment, this binding 3가지이다.
Variable Environment | Environment Record: 식별자 정보 |
Outer Environment Reference: 선언될 당시의 Lexical 참조 | |
Lexical Environment | Environment Record: 식별자 정보 |
Outer Environment Reference: 선언될 당시의 Lexical 참조 | |
This Binding | this로 지정된 객체 |
Variable Environment는 현재 컨텍스트 내의 식별자들에 대한 정보와 외부환경정보를 담고있고, 선언시점의 스냅샷이여서 변경사항은 반영되지 않는다. 그에 비해 Lexical Environment는 변경사항이 실시간으로 반영된다. This Binding은 this식별자가 바라봐야할 대상 객체에 대한 정보를 갖게된다.
2. 호이스팅
Environment Record에는 현재 컨텍스트와 관련된 코드의 식별자 정보들이 저장되게되는데, 컨텍스트 내부전체를 처음부터 끝까지 순서대로 수집하게된다. 이때, 코드가 실행되기 전임에도 불구하고 자바스크립트엔진은 식별자에 대한 정보를 갖게되는것이고, 이는 '식별자들을 최상단으로 끌어올려놓은다음 실제코드를 실행한다'라고 할수있는데 이 개념이 호이스팅이다. 호이스팅에서는 변수명만 끌어올리고 할당과정은 그대로 남겨두게된다.
호이스팅에 있어서 함수선언문과 함수표현식의 차이점을 알아야한다. 함수선언문을 사용할 경우에는 함수명이 곧 변수명이기 때문에 함수전체가 호이스팅되지만, 함수표현식은 선언부변수만 호이스팅이 되게된다.
위의 예시에 의하면 함수선언문은 전체가 호이스팅되어 정상적으로 작동하는 반면에, 함수표현식은 선언부변수만 호이스팅이 되어 런타임오류가 일어난다. 하지만 그럼에도 불구하고 함수표현식을 써야하는 이유는 안전하기 때문이다. 코드가 작성순서에 의하여 차례대로 실행되게끔, 선언 이후의 코드들에서만 안전하게 동작하게끔 해주기 위해서는 함수표현식을 사용하는 것이 좋다.
3. 스코프체인
스코프란 식별자에 대한 유효범위로, ES5까지는 스코프는 오직 함수에 의해 생성이 되었었다. 식별자의 유효범위를 안에서부터 바깥으로 차례대로 탐색해 나가는 것을 스코프체인이라고 한다. Outer Environment Reference는 현재 호출된 함수가 선언될 당시의 Lexical Environment를 참조하게 된다. 즉 A함수 내부에 B함수를 선언했다면, B함수의 Lexical Environment에 존재하는 Outer Environment Reference는 A의 Lexical Environment를 참조하게 되는 것이다. 만약 여러 스코프에서 동일한 식별자를 선언한 경우에는 스코프체인상에서 가장 먼저 발견된 식별자에만 접근 가능하게된다. 여기서 변수은닉화라는 개념이 등장하는데, 함수내부에서 이미 선언한 변수에 대해서는 전역공간에 접근이 불가능한 것을 말한다.
자바스크립트에서 전역변수란 전역컨텍스트의 Lexical Environment에 담긴 변수를 말하며, 지역변수는 그밖의 함수에 의해 생성된 실행컨텍스트의 변수를 말한다. 코드의 안전성을 위해서는 가급적 전역변수의 사용을 최소화하는 것이 좋은데, 그 이유는 전역공간에 같은 변수명의 함수를 선언하더라도 이미 지역변수로 선언을 했다면 코드 대부분이 함수내부에서 동작하게되어 전역공간에서 접근할 수 없게 되기때문이다. ES6에서는 let, const, class, strict와 같은 블록에 의해서도 스코프 경계가 발생한다.
✨ 이 글은 정재남님의 코어자바스크립트를 참고하여 작성된 글입니다. 프론트엔드 개발자라면 꼭 사서 읽어보시는 것을 추천드립니다.
'JS' 카테고리의 다른 글
[JS] 콜백함수, 콜백지옥 (0) | 2022.05.13 |
---|---|
[JS] This, Binding (0) | 2022.05.12 |
[JS] 자바스크립트 데이터 타입 (0) | 2022.05.11 |
[JS] 클로저 개념 (2) | 2020.11.26 |