모던 자바스크립트 입문
아소 히로시 지음, 서재원 옮김
길벗
모던 자바스크립트 입문
8.5 프로그램의 평가와 실행 과정
을 보고나서 이 부분은 자바스크립트를 공부, 사용함에 있어서 매우 중요하다고 생각 되어서 별도로 정리 하였다. 내가 모르는 부분도 상당하였고 이해가 가지 않은 부분은 다른 사이트도 참조 하였다.
8.5 프로그램의 평가와 실행 과정
-
실행 가능한 코드(Excutable Code)
- 자바스크립트 엔진은 실행 가능한 코드를 만나면 그 코드를 평가해서
실행 문맥(Excution Context)
를 만든다. -
실행 가능한 코드의 유형은 다음과 같다.
-
전역 코드
- window 전역 객체 아래 정의된 함수
-
함수 코드
- 함수 코드
-
eval 코드
- eval 함수
렉시컬 환경(Lexical Environment)
이 아닌 별도의 동적 환경에서 실행된다.
-
- 자바스크립트 엔진은 실행 가능한 코드를 만나면 그 코드를 평가해서
-
실행 문맥(Excution Context)
- 실행 가능한 코드가 실제로 실행되고 관리되는 영역
-
실행에 필요한 모든 정보를 컴포넌트 여러 개로 나누어 관리한다.
렉시컬 환경(LexicalEnvironment)
컴포넌트변수 환경(VariableEnvironment)
컴포넌트-
디스 바인딩(This Binding)
컴포넌트- 함수를 호출한 객체의 참조가 저장되는 곳
- 이것이 가리키는 값이 실행 문맥의
This
가 된다.
- 렉시컬 환경 컴포넌트와 변수 환경 컴포넌트는 타입이 같고, with문을 사용할 때를 제외하곤 내부 값이 똑같아 같은 취급을 해도 된다.
-
렉시컬 환경 컴포넌트
- 자바스크립트 엔진이 자바스크립트 코드를 실행하기 위해 자원을 모아둔 곳
- 함수 또는 블록의 유효 범위 안에 있는 식별자와 그 결과값이 저장되는 곳
-
자바스크립트 엔진은 유효 범위안에 있는 식별자와 그 식별자가 가리키는 값을
키와 값 쌍으로 바인드 한다.
-
환경 레코드(Environment Record)
- 유효 범위 안에 포함된 식별자를 기록하고 실행하는 영역
- ECMAScript 3의 변수 객체와 비슷한 역할을 한다.
- 자바스크립트 엔진은 유효 범위 안의 식별자와 결과값을 바인드해서 환경 레코드에 기록한다.
-
외부 렉시컬 환경 참조(Outer Lexical Environment Reference)
컴포넌트- 자바스크립트는 함수안에 함수를 중첩해서 정의할 수 있다. 따라서 유효 범위 너머의 유효 범위도 검색 할 수 있어야 한다.
- 함수를 둘러싸고 있는 코드가 속한 렉시컬 환경 컴포넌트의 참조가 저장된다.
- 중첨된 함수 안에서 바깥 코드의 정의된 변수를 읽거나 사용할 때
외부 렉시컬 환경 참조
를 따라 변수를 검색한다.
-
-
환경 레코드
-
레시컬 환경 안의 식별자와 그 식별자가 가리키는 값의 묶음이 실제로 저장되는 영역이다.
-
선언전 환경 레코드(Declarative Environment Record)
- 실제로 함수와 변수, catch문의 식별자와 실행 결과거 저장된다.
-
객체 환경 레코드(Object Environment Record)
- 실행 문맥 외부에 별도로 저장된 객체의 참조에서 데이터를 읽거나 사용한다.
- 렉시컬 환경이나 전역 객체처럼 별도로 저장된 데이터는 키와 쌍을 복사하는 것이 아닌, 해당 객체의 참조를 가져와서 객체 환경 레코드의
bindObject
라는 프로퍼티에 바인드하여 사용한다.
-
-
-
전역 환경과 전역 객체의 생성
- 자바스크립트 인터프리터는 시작하자마자 렉시컬 환경 타입의
전역 환경(Global Environment)
을 생성한다. -
그다음 전역 객체를 생성한 다음 전역 환경의 객체 환경 레코드에 전역 객체의 참조를 대입한다.
// 전역 환경 GlobalEnvironment = { ObjectEnvironmentRecord: { bindObject: window }, OuterLexicalEnvironmentReference: null } // 전역 실행 문맥 ExcutionContext = { LexicalEnvironment: GlobalEnvironment, ThisBinding: window }
- 자바스크립트 인터프리터는 시작하자마자 렉시컬 환경 타입의
-
프로그램의 평가와 전역 변수
- 전역 환경과 전역 객체를 생성한 후에는 자바스크립트 프로그램을 읽어 들인다.
-
자바스크립트 프로그램을 다 읽어 들인 후 프로그램을 평가하며, 최상위 레벨에 var문으로 작성한 전역 변수는 전역 환경의 환경 레코드의 프로퍼티로 추가 된다.
var TEST1 = "TEST1"; var TEST2 = "TEST2"; console.log(window.TEST1) // TEST1 console.log(window.TEST2) // TEST2 function TEST3 (a) => { .... } console.log(window.TEST3) // TEST3(a)
전역 변수는 전역 객체 프로퍼티의 또는 전역 객체의 실행 문맥에 들어있는 환경 레코드의 프로퍼티이다.
- 최상위 레벨에 선언된 변수와 함수는 프로그램을 평가하는 시점에 환경레코드에 추가 된다. 평가 단계에서 이미 객체 환경 레코드에 추가된 상태이기 때문에 어느 위치에서 작성해도 사용할수 있게 된다. 이게
호이스팅(hoisting)
이다. - var 문과 함수 선언문으로 선언한 전역 변수는
[[Configualble]]
속성이false
로 설정되어 있어서delete
연산으로 삭제가 불가능하다. - var문을 사용하지 않고 변수를 선언해서 값을 할당하면 프로그램을 실행하는 도중에 디스 바인딩 컴포넌트가 가리키는 객체의 프로퍼티로 추가된다. 디스 바인딩 컴포넌트가 전역객체를 가리키므로 결국
전역 객체
가 되는 것이다. 하지만[[Configualble]]
속성이true
로 되어 있기 때문에delete
연산으로 삭제가 가능하다.
-
프로그램 실행과 실행 문맥
- 프로그램이 평간된 뒤 프로그램이 실행되며, 프로그램은
실행 문맥(Excutable Context)
안에서 실행된다. -
실행 문맥은 실행 가능한 코드(전역 코드, 함수 코드, eval 코드)별로 생성된다.
- 실행 문맥은
스택(stack)구조
로 관리된다. 이를호출 스택(call stack)
이라 부른다. - 전역 코드가 가장 먼저 실행된다. 전역 코드안에 함수가 있다면 함수를 실행 하기위한 문맥을 스택에 push하고 함수가 끝나면 이를 pop한다. 이때 함수가 중첩함수라면 중첩 함수의 실행 문맥을 새로 만들어서 스택에 push-pop한다.
- 실행 문맥은
- 프로그램이 평간된 뒤 프로그램이 실행되며, 프로그램은
-
싱글 스레드
- 자바스크립트는 싱글 스레드 방식이다. 즉, 실행 문맥 단위의 작업을 차례대로 실행 하므로 실행 문맥(함수나 코드)하나의 작업이 끝날 때까지 또 다른 실행 문맥의 작업을 실행하지 않는다.
-
환경 레코드와 지역 변수
-
함수 호출시 내부적으로 발생하는 일
(1)함수 호출 (2)실행 코드 중지 (3)실행 문맥 생성 (4)실행 문맥으로 이동 (5)호출 스택에 Push (6)렉시컬 환경 컴포넌트 생성 (7)함수의 환경 기록, 디스 바인딩(This Binding) 컴포넌트에 그 함수를 호출한 객체를 기록 (8)함수안의 코드가 순차적으로 실행 (9)함수 종료 (10호출한 코드로 이동, 만들어진 실행 문맥과 렉시컬 환경 컴포넌트가 메모리에서 삭제
- 디스 바인딩(This Binding)에 해당 함수를 호출하는 객체가 기록되는데, 이것이
This
값을 결정 짓는다.
- 디스 바인딩(This Binding)에 해당 함수를 호출하는 객체가 기록되는데, 이것이
-
-
This
- 함수가 호출되어 실행되는 시점에 This 값이 결정된다.
- This는
함수가 호출되었을 때, 그 함수가 속해 있던 객체의 참조
이다.
const add = { x: 10, y: 11, sum: function() { console.log(this); return this.x + this.y; } }; console.log(add.sum()); // 결과 // { x: 10, y: 11, sum: [Function: sum] } // 21 //
sum
이 속한 객체는add
이다.sum
메서드가 호출되는 실행 문맥의 디스 바인딩 컴포넌트가 가리키는 객체는 add가 된다.- 다양한 상황별 This
-
최상위 레벨 코드의 this
- 전역 객체를 가리킨다. 실행 문맥이 초기화될 때 디스 바인딩 컴포넌트가 전역 환경을 가리킨다.
-
이벤트 처리기 안에 있는 this
- 이벤트가 발생한 요소 객체를 가리킨다.
-
생성자 함수 안에 있는 this
- 사용자가 정의한 생성자 함수 안에 있는 this는 생성자로 생성한 객체를 가리킨다.
-
생성자의 prototype 메서드 안에 있는 this
- 생성자의 prototype 메서드 있는 this는 생성자로 생성한 객체를 가리킨다.
-
직접 호출한 함수 안에 있는 this
- 최상위 레벨에서 호출한 함수 안의 this는 전역객체를 가리킨다.
- 어떤 객체를 부여 호출하면 this는 해당 객체를 가리킨다.
-
apply
,call
메서드로 호출한 함수 안에 있는 thisapply
와call
메서드를 사용하면 함수를 호출할 때 this가 가리키는 객체를 바꿀수 있다. 즉 두 함수는 함수 객체가 실행되는 실행 문맥의 디스 바인딩 컴포넌트가 가리키는 객체를 설정 할 수 있다.
-
유효범위 체인(스코프 체인)
- 간단히 정리하면 유효 범위 안에 없는 식별자를 찾을 경우 외부 렉시컬 환경의 참조를 따라 찾는다고 보면 된다.
이 코드는 모던 자바스크립트 입문(徹底マスターJavaScriptの教科書) 에서 인용한 것입니다.
[ISBN #978-4797388640]. Copyright 2017 by 磯博