코어자바스크립트_02. 실행 컨텍스트
02 실행 컨텍스트
목표 : 자바스크립트의 실행 컨텍스트를 이해하고, 자바스크립트의 성격을 파악한다
2-1. 실행 컨텍스트란?
실행 컨텍스트 : 실행할 코드에 제공할 환경 정보를 모아놓은 객체
하나의 실행 컨텍스트를 구성할때는 콜스택으로 쌓아 올렸다가, 가장 위에 있는 컨텍스트부터 하나씩 실행한다.
이런 구조의 자바스크립트 파일이 있다고 치자. 이 파일이 실행될때 전역컨텍스트가 콜스택에 담기면서 실행컨텍스트가 전역컨텍스트 위로 스택에 쌓이게 된다.
자바스크립트 파일이 열리는 순간 브라우저는 전역컨텍스트를 활성화시키고 전역컨텍스트를 읽어 내려가면서 실행컨텍스트를 콜스택에 담는다.
스택 구조에 따라서 가장 상단의 실행컨텍스트로 인해 전역컨텍스트는 중단되고, 실행컨텍스트가 실행된다.
2-2. Variable Enviromnment
실행컨텍스트 객체 내부 Variable Enviromnment (environmentRecord_snapshot/outerEnvironmentReference_snapshot) Lexical Environment (environmentRecord/outerEnvironmentReference) ThisBinding
Variable Enviromnment는 최초 실행 시의 스냅샷을 유지한다.Variable Enviromnment을 복사해서 Lexical Environment을 주로 사용한다.
2-3. LexicalEnvironment
2-3-1. environmentRecord와 호이스팅
현재 컨텍스트와 관련된 코드의 식별자 정보 저장한것
변수의 식별자, 함수 자체…
environmentRecord에 식별자가 저장 되었다고 해도 코드가 실행되기 전이다.
코드가 실행되기 전에 environmentRecord에 식별자가 저장되기때문에 자바스크립트에서 호이스팅이라는 개념이 중요하게 된다.
호이스팅
처음 자바스크립트를 공부할때 배웠던 호이스팅은 함수 선언문 function a (){} 은 호이스팅이 되어 함수 선언보다 위에서 호출해도 문제없이 실행되지만, 함수표현식 const b= function a (){} 은 함수를 선언하기전에 호출하면 버그가 생긴다. 딱 이정도 지식이였다. 여기서 더 깊게 들어가보자.
environmentRecord는 식별자와 함수가 코드가 실행되기전에 저장된다고 했다.
이 흐름대로라면 당연히 함수를 식별자에 할당하는 함수표현식의 함수는 environmentRecord에 저장되지 않는다.
그렇기 때문에 협업을 할때 주의사항이 생기게 된다. 함수 선언문은 호이스팅이 된다고 했다. 이 말을 책의 예제대로 100번째 줄에 a함수를 선언하여 사용했는데 500번째 줄에 또 a함수를 사용하면 해당 프로젝트에서는 500번째 줄에 사용한 a함수만 남게 된다. 100번째 줄에 a함수를 작성한 개발자는 영문도 모르게 다른사람이 만든 함수를 사용하게 되어 개발자의 의도와 다르게 버그가 생기게 된다. 이런 불상사를 막기 위해 기능을 위한 함수는 함수 표현식을 사용해서 버그를 예방하는것이 좋다.
함수 표현식이 안정적이고 좋은데, 왜 함수 선언문이 있는가?라는 의문이 든다.
이는 코드의 가독성과 유지보수성의 장단점에 따라 구분하여 사용하면된다. 함수 선언문 function a (){}은 호이스팅이 되어 함수 자체가 먼저 저장되기 때문에 코드의 구조나 호출 순서에 대한 혼란이 적다. 그렇기 때문에 큰 범위에서 사용하면 된다. 함수 표현식 const b= function a (){}은 변수에 선언된 함수의 스코프가 명확하기 때문에 변수 오염을 예방하여 코드의 안정성을 높일 수 있다.
여기서 스코프가 무엇인가?
2-3-2. 스코프, 스코프 체인, outerEnvironmentReference
스코프는 식별자에 대한 유효범위이다. 예를 들어 식별자 a와 함수b, 함수b 안에 식별자c가 있다고 하면, a는 함수 b에서 사용할 수 있지만, c는 함수b밖에서 사용할 수 없다. 이것이 스코프이다. 그리고 사용가능한 것을 outerEnvironmentReference를 수집하기 때문이다.
스코프체인
잠시 2-2. Variable Enviromnment로 돌아가보자,
1
2
3
4
5
6
7
8
실행컨텍스트 객체 내부
Variable Enviromnment → 현재 컨텍스트 내의 식별자들에 대한 정보 + 외부 환경정보, 선언시점의 스냅샷, 변경사항 저장 안됌
(environmentRecord_snapshot)
(outerEnvironmentReference_snapshot)
Lexical Environment → 처음에는 Variable Enviromnment와 같지만 변경사항이 실시간으로 반영됨
(environmentRecord)
(outerEnvironmentReference)
ThisBinding → this식별자가 바라봐야할 대상 객체
스코프 체인의 체인이라는 단어에서도 알수 있듯이 다른 식별자의 스코프, 즉 유효범위 내의 있는것을 사용 검색하는 것이다.
아래에서 위로 올라가보면, outerEnvironmentReference는 감싸고 있는 함수의 Lexical Environment을 참조한다. 그럼 감싸고 있는 함소는 outerEnvironmentReference가 있고 또 위의 함수의 Lexical Environment을 참조한다. 이렇게 서로가 서로를 참조하는 형태 덕분에 다른 스코프에 있는 식별자를 검색할 수 있는것이다. 하지만 모든 식별자를 검색 할 수 있는것은 아니다. 스코프 체인을 통해 다른 스코프를 검색하면 동일한 이름으로 선언된 가장 먼저 발견된 식별자만 접근이 가능하다. 이러한 특성을 통해 변수 은닉화를 할 수 있다.
전역변수와 지역변수
자바스크립트를 배우고 프로젝트를 진행하다보면 자연스럽게 익히는 개념 중 하나이다.
여기서 전문? 배운 용어를 사용해서 있어보이게 다시 정리해보자.
전역변수 : 전역 스코프에서 선언한 변수 지역변수 : 함수/블록 스코프에 선언된 변수
호이스팅의 함수의 종류에서 이야기했던 것과 비슷한 맥락으로 지역변수가 코드의 안전성이 높기 때문에 전역변수의 사용을 최소화하는것이 좋다.