📢 어렵고 정석적인 개념 설명보다는 저같은 초보자도 이해하기 쉽게 정리하는 것을 원칙으로 포스팅하고 있습니다. 😄
개념
해당 글은 자바스크립트 엔진의 입장에서 함수를 호출했을 때 준비-초기화-실행 단계 중 준비 과정에서의 실행문 생성과 실행 과정을 글쓴이 한 사람의 입장에서 보기 쉽게 정리한 글이다.
따라서 다른 자바스크립트 교재나 실제 자바스크립트 엔진의 논리 구조와 비슷할 지는 몰라도 내용의 깊이 정도는 다를 수 있다. 그저 이해하기 쉽게 정리한 글임을 다시 한 번 더 강조하는 바이다.
함수가 작동하는 데에는 총 3가지의 단계를 거친다.
준비 단계 - 초기화 단계 - 실행 단계로 준비 단계에서는 실행 컨텍스트를 생성하고 스코프, 변수와 함수, this 바인딩 등 함수를 실행하는 데 필요한 기본의 것들을 실행 컨텍스트에 저장(참조)하는 단계이다.
초기화 단계는 준비 단계에서 정리된 변수와 함수 값에 undefined 값을 넣어 실제 값이 할당되기 전 상태로 만들어주는 단계이다.
마지막 실행 단계는 준비 단계에서 선언된 변수와 함수에 실제 값을 할당해주고, 함수 코드를 실행해준다. 이렇게 자바스크립트 엔진은 총 3단계를 거쳐 함수를 실행시킨다.
이 글에서 다룰 것은 바로 3단계 중 첫 번째 단계인 '준비 단계'를 다룬다. 준비 단계에서 가장 중요한 키워드는 바로 실행 컨텍스트(Execution Context)이다.
실행 컨텍스트는 렉시컬 환경 컴포넌트, 변수 환경 컴포넌트, this 바인딩 컴포넌트로 구성되어 있다.
렉시컬 환경 컴포넌트
렉시컬 환경 컴포넌트는 환경 레코드와 외부 렉시컬 환경 참조로 나뉘어진다. 여기서 환경 레코드는 다시 선언적 환경 레코드와 오브젝트 환경 레코드로 나뉘어진다.
즉, 렉시컬 환경 컴포넌트는 선언적 환경 레코드, 오브젝트 환경 레코드, 외부 렉시컬 환경 참조로 구성된다고 볼 수 있다.
먼저 선언적 환경 레코드는 사실상 함수에서 가장 중요한 내용을 담고 있는 곳이라고 보면 된다.
함수 안의 변수와 함수의 이름과 값을 바인딩하고 함수를 호출할 때의 파라미터 값을 호출된 함수의 파라미터 이름에 매핑한다.
오브젝트 환경 레코드는 쉽게 말해서 글로벌 오브젝트의 변수와 함수를 바인딩하는 역할을 한다고 생각하면 된다. 즉, 전역 변수/함수를 불러올 때 여기서 값을 가져온다. (동적 환경이다)
외부 렉시컬 환경 참조는 함수가 호출될 때 생성됐던 [[Scope]]를 여기서 참조한다. 또한 함수 밖의 변수와 함수를 바인딩한다. 선언적 환경 레코드가 함수 안이라면 여기서는 함수 밖인 것이다.
변수 환경 컴포넌트
변수 환경 컴포넌트와 렉시컬 환경 컴포넌트의 초기값은 서로 동일하다.
하지만, 렉시컬 환경 컴포넌트는 함수 코드가 실행되고 초기화 단계를 지나면서 값이 변하게 된다.
이에 반해 변수 환경 컴포넌트는 초기값 그대로 보존(유지)한다. 쉽게 생각하면 렉시컬 환경 컴포넌트의 초기값 사본(?)이라고 생각하면 된다. 변수 환경 컴포넌트가 필요한 이유는 렉시컬 환경 컴포넌트의 값이 초기값으로 돌아오는 경우를 대비해서 준비하기 위함이다. 변수에 새로운 값이 할당되기도 하지만, 할당된 값을 삭제할 수도 있다. 이 때 변수 환경 컴포넌트에서 초기값인 undefined 값을 가져오는 것이다.
this 바인딩 컴포넌트
this 바인딩 컴포넌트는 우리가 함수 안에 this를 쓸 때, this에 어떤 오브젝트의 값을 가져올 지 오브젝트의 정보를 참조하기 위한 역할을 수행한다. 예를 들어, obj.name()이 호출됐다고 하면 this 바인딩 컴포넌트는 obj 오브젝트를 참조하게 된다. this 바인딩 컴포넌트는 렉시컬 환경 컴포넌트와 달리 동적 환경이기 때문에, obj의 프로퍼티가 변경되면 this 바인딩 컴포넌트도 동시에 변경된다는 특징을 갖고 있다.
정리
코드 하나 없이 글로만 정리해서 처음 글을 읽는 사람 입장에서는 이게 무슨 말인가 싶을 수도 있다.
나도 내가 작성했지만, 며칠 지나면 바로 까먹을 것 같은 불길한 예감에 나를 포함한 모두를 위해서 한 눈에 보면 '대충'이라도 이해 될 만한 논리 구조 그림을 그려봤다.
실행 컨텍스트: {
렉시컬 환경 컴포넌트: {
환경 레코드: {
선언적 환경 레코드: {},
오브젝트 환경 레코드: {}
},
외부 렉시컬 환경 참조: {}
},
변수 환경 컴포넌트: {},
this 바인딩 컴포넌트: {}
}
함수 실행문의 논리 구조는 다음과 같다. 함수를 호출하는 순간 실행문이 만들어지게 되고, 각각의 항목에서 변수, 함수, 파라미터, 스코프, this 등 함수와 관련된 여러 요소들의 정보를 하나의 실행문이 참조하게 된다. 즉, 자바스크립트 엔진 입장에서는 이 실행문 하나에 모두 정리가 되어 있기 때문에 땡잡은 셈이다.
'JavaScript' 카테고리의 다른 글
[JavaScript] 특정 요소가 화면 끝에 닿으면 이벤트 발생시키기 (0) | 2022.03.07 |
---|---|
[JavaScript] 시간 지연 함수 setTimeout() / setInterval() (0) | 2022.01.26 |
[JavaScript] 자바스크립트 함수 실행 과정과 호이스팅 (0) | 2022.01.18 |
[JavaScript] 중복 체크에 활용하면 좋은 indexOf() (0) | 2022.01.17 |
[JavaScript] 자바스크립트 ES5 프로퍼티 descriptor (0) | 2022.01.14 |