Bleeding edge

2022/08/22 - TIL 본문

ConnecTo

2022/08/22 - TIL

codevil 2022. 8. 22. 19:19

실행 컨텍스트

1. 소스코드의 타입

소스코드는 실행컨텍스트를 생성한다. 소스코드는 ECMAScript 사양으로 4가지로 구분한다

[전역 코드, 함수 코드, eval 코드, 모듈 코드]

소스코드의 타입에 따라 실행 컥텍스트를 생성하는 과정관리 내용이 다르다.

| 전역 코드 | 전역 스코프(최상위 스코프)를 생성한다(전역 변수, 전역 함수 관리를 위해). 전역변수(var), 전역함수(함수 선언문)를 전역 객체의 프로퍼티와 메서드로 바인딩하고 전역 객체와 연결한다 전역 코드가 평가되면 전역 실행 컨텍스트가 생성된다 | | --- | --- | | 함수 코드 | 지역 스코프를 생성한다(매개변수, arguments 객체 관리를 위해) 지역 스코프를 전역 스코프에서 시작하는 스코프 체인의 일원으로 연결한다 함수 코드가 평가되면 함수 실행 컨텍스트가 생성된다 | | eval 코드 | strict mode에서 자신만의 독창적인 스코프를 생성한다. eval 코드가 평가되면 eval 실행 컨텍스트가 생성된다 | | 모듈 코드 | 모듈 코드는 모듈별로 독립적인 모듈 스코프를 생성한다. 모듈코드가 평가되면 모듈 실행 컨텍스트가 생성된다 | | | |

2. 소스 코드의 평가와 실행

소스코드 평가 과정

  1. 실행컨텍스트를 생성
  2. 변수, 함수 선언문만 먼저 실행 ⇒ 변수 식별자, 함수 식별자 생성
  3. 함수 식별자를 실행 컨텍스트가 관리하는 스코프에 등록

소스코드 실행 과정

  1. 선언문을 제외한 소스코드가 순차적으로 실행
  2. 변수나 함수의 참조(소스코드 실행에 필요한)를 관리하는 실행 컨텍스크가 스코프에서 검색
  3. 소스코드의 실행 결과(변수 값의 변경)은 스코프(실행 컨텍스트가 관리하는)에 등록

3. 실행 컨텍스트의 역활

  1. 전역 코드 평가 : 전역코드의 선언문(변수, 함수)만 먼저 실행 ⇒ 전역 변수 전역 함수 생성
  2. ⇒전역 변수 전역 함수 전역 스코프에 등록||전역변수(var), 전역함수(함수 선언문)은 전역 객체의 프로퍼티와 메서드가 된다
  3. 전역 코드 실행 : 전역 코드가 순차적으로 실행 ⇒ 변수에 값이 할당되고 함수 호출
  4. 함수가 호출되면, 전역 코드 실행은 일시중단 ⇒ 함수 내부 진입
  5. 함수 코드 평가 : 매개변수와 지역 변서 선언문을 먼저 실행 ⇒매개 변수와 지역 변수가 지역 스코프(실행컨텍스트가 관리하는)에 등록 || 함수 내부에서 사용할 수 있는 arguments 객체가 생성되어 지역스코프에 등록 || this 바인딩도 결정
  6. 함수 코드 실행 : 매개 변수와 지역분수 값이 할당 ⇒ 스코프 체인을 이용하여 메서드를 검색 ⇒ 함수 코드가 끝 ⇒전역 함수 실행

코드를 실행하려면 스코프, 식별자, 코드 실행순서를 관리 해야한다.

실행 컨텍스트는 식별자를 등록하고 관리하는 스코프와 코드 실행 순서 관리를 구현한 내부 매커니즘으로 모든 코드는 실행 컨텍스트를 통해 실행되고 관리된다.

식별자와 스코프는 실행 컨텍스트의 렉시컬 환경으로 관리하고

코드 실행 순서는 실행 컨텍스트 스택으로 관리한다

4. 렉시컬 환경

실행 컨텍스트 스택이 실행 순서를 관리한다면, 렉시컬 환경은 스코프와 식별자를 관리한다

렉시컬 환경은 식별자를 키로, 바인딩 된 값을 값으로 관리한다. 렉시컬 환경은 스코프를 구분하여 식별자를 등록하고 관리하는 저장소 역활을 하는 렉시컬 스코프의 실체이다

실행 컨텍스트는 렉시컬 환경 컴포넌트와 변수 환경 컴포넌트으로 구성된다. 처음에는 렉시컬 환경 컴포넌트와 변수 환경 컴포넌트는 하나의 동일한 렉시컬 환경을 참조하지만, 몇 가지 상황을 만나면 변수 환경 컴포넌트를 위한 새로운 렉시컬 환경이 생성되고, 두 컴포넌트의 내용이 달라진다. (지금부터는 컴포넌트로 구분하지 않고 렉시컬 환경으로 통일하여 설명한다)

렉시컬 환경은 환경레코드와 외부렉시컬환경참조 컴포넌트로 구성된다

5. 실행 컨텍스트의 생성과 식별자 검색 과정

  1. 전역 객체 생성 : 전역 객체는 전역 코드가 평가되기 이전에 생성된다. ⇒ [1] 전역객체에 빌트인(빌트인 전역 프로퍼티, 빌트인 전역 함수, 표준 빌트인 객체, 호스트 객체를 포함)를 추가전역객체는 [2] Object.prototype를 상속받는다. (전역 객체는 프로토타입 체인의 일원)
  2. 전역 코드 평가(전역 실행컨텍스트 생성 후 실행 컨텍스트 스택으로 푸시후 시작)
1. 전역 실행 컨텍스트 생성
1-1. 전역 렉시컬 환경 생성
1-1-1. 전역 환경 레코드 생성
1-1-1-1. 객체 환경 레코드 생성(var) - BindingObject와 연결(전역 객체)
1-1-1-2. 선언적 환경 레코드 생성(let, const)
1-1-1-[[3]] this 바인딩
1-1-2 외부 렉시컬에 대한 참조 결정(상위 스코프)
1-1-1-1 에서 객체 환경 레코드생성과 BindingObject가 연결되어 있기 때문에, var을 통하여
선언을 하면, BindingObject를 통해 전역 객체에 변수 식별자를 키로 등록하여 암묵적으로
undefined를 바인딩한다.
함수 선언문은, BindingObject를 통해 전역 객체에 키로 등록하고 선언된 함수를 즉시
할당하기 때문에 함수 호이스팅과, 변수 호이스팅의 차이가 난다.

1-1-1-2 선언적 환경 레코드는 전역 객체의 프로퍼티가 되지 않고 개념적인 블록에 존재한다

1-1-1-[[3]]전역 환경 레코드의 [[GlobalThisValue]] 내부 슬롯에 this가 바인딩된다.
일반적으로 전역 객체를 가리키므로 전역 환경 레코드의 [[GlobalThisValue]] 내부 슬롯에는
전역 객체가 바인딩된다.전역 코드에서 this를 참조하면 전역 환경 레코드의
[[GlobalThisValue]] 내부 슬롯에 있는 값이 반환된다.
(함수의 경우에는 GlobalThisValue가 아니라 ThisValue 내부 슬롯으로 저장된다)

1-1-1-1과 1-1-1-2에는 this바인딩이 없고 1-1-1에만 this 바인딩이 존재한다

1-1-2 외부 렉시컬 환경에 대한 참조는 현재 평가중인 소스코드의 상위 스코프(외부 소스코드
의 렉시컬 환경)를 가리킨다.
전역 렉시컬 환경의 외부 렉시컬에 대한 참조는 null이 된다.
(일반 함수의 경우에는 전역 렉시컬 환경 혹은 그위의 스코프로 저장된다)

6. 실행 컨텍스트와 블록 레벨 스코프

let const 키워드로 선언한 변수는 모든 코드블록을 지역 스코프로 인정하는 블록레벨 스코프다
if 문의 코드블록이 실행되면, if 문의 코드 블록을 위한 블록 레벨 스코프를 생성해야한다
이를 위해 선언적 환경 레코드를 갖는 렉시컬 환경을 새롭게 생성하여 기존의 전역 렉시컬
환경을 교체한다.
블록 렉시컬 환경은 환경레코드와, 외부렉시컬환경 참조 두가지를 컴포넌트로 가지고 있다
환경 레코드는 선언적 환경 레코드로 연결되며, 외부 렉시컬 환경은 외부 스코프로 연결된다.

클로저

클로저는 함수와 그 함수가 선언된 렉시컬 환경과의 조합이다.

1. 렉시컬 스코프

자바스크립트 엔진은 함수를 어디서 호출했는지가 아니라 함수를 어디서 정의했는지에 따라

상위 스코프를 결정한다. 이를 렉시컬 스코프(정적 스코프)라 한다.

스코프의 실체는 실행 컨텍스트의 렉시컬 환경이다.

렉시컬 환경은 자신의 외부 렉시컬 환경에 대한 참조를 통해 상위 렉시컬 환경과 연결된다.

이것이 바로 스코프 체인이다.

상위 스코프(렉시컬 환경의 외부 렉시컬 환경에 대한 참조 값)는 함수 정의가 평가되는 시점에 함수가 정의된 환경에 의해 결정된다. ⇒렉시컬 스코프

2. 함수 객체의 내부 슬롯 [[Environment]]

정적인 스코프가 가능하려면, 호출된 환경과 상관 없이 정의된 환경을 기억해야 한다. 즉 상위 스코프를 기억해야 한다. 이를 위해 함수는 자신의 내부 슬롯 [[Environment]]에 상위스코프(자신이 정의된 환경)을 저장한다.

3. 클로저와 렉시컬 환경

외부 함수보다 중첩함수가 더 오래 유지되는 경우 중첩함수는 이미 생명 주기가 종료한 외부 함수의 변수를 참조할 수 있다. 이러한 중첩함수를 클로저라고 부른다.

outer 함수의 실행이 종료하면 inner함수를 반환하면서 outer 함수의 생명 주기가 종료된다. outer 함수의 실행 컨텍스트가 실행 컨텍스트 스택에서 제거된다. 이때 outer 함수의 실행 컨텍스트는 실행 컨텍스트 스택에서 제거되지만, outer 함수의 렉시컬 환경까지 소멸하는 것은 아니다

const x =1;
function outer(){
	const x = 10;
	const inner = function(){
	return inner;
	}
}
const innerFunc() = outer();
innerFunc();

outer 함수의 렉시컬 환경은 inner 함수의 Environment 내부 슬롯에 의해 참조되고 있고 inner 함수는 전역 변수 innerFunc에 의해 참조되고 있으므로 가비지 컬렉션의 대상이 되지 않는다.

inner -[[Environment]]-> outer
innerFunc -[[Environment]]->inner 

가비지 컬렉터는 누군가가 참조하고 있는 메모리 공간은 함주로 해제하지 않는다.

주의!! 순서는 
Global EC -lexicalEnvironment->Global Lexical Environment
Global Lexical Environment-GlobalEnvironRecord->Object Environment Record
Object Environment ReCord -Binding Object->
window -outer->outer function object
outer functionobject[[Environment]]-Global Lexical Environment
연결된 이후에 outer이 호출되면, EC Stack으로 Outer EC가 push된다.

inner도 마찬가지로 outer의 Function Environment Record -inner ->inner Function object
연결이 된후에 inner Function이 호출되면 inner EC가 stack으로 push된다

클로저의 조건

  1. 중첩함수가 상위 스코프의 식별자를 참조(상위 스코프에 있는 변수사용)
  2. 상위 스코프보다 오래 생존

상위 스코프의 식별자 중에서 클로저가 참조하고 있는 식별자만을 기억한다

클로저에 의해 참조되는 상위 스코프의 변수를 자유변수라고 부른다. 클로저란, 함수가 자유변수에 대해 다쳐있다라는 의미이다.(자유변수에 묶여있는 함수)

4. 클로저의 활용

클로저는 상태를 안전하게 변경하고 유지하기 위해 사용한다

상태를 의도치않게 변경하지 않도록 상태를 안전하게 은닉하고 특정 함수에게만 상태 변경을 허용하도록 한다.

const increase = (function(){
	let num = 0;
	return function (){
		return ++num;
	}
})
console.log(increase());//1
console.log(increase());//2
console.log(increase());//3

수업시간에 메모한 것

변수 선언은 자바스크립트에게 변수라는 식별자를 자바스크립트엔진에게 알린다. 이것을 기억해야 하기때문에 실행 컨텍스트에 저장해야한다. 식별자가 평가 단계에서 만들어지니까, 빈걸 만들고 실행 컨텍스트 스택에 넣는다. 식별자를 하나씩 채운다.

현재 실행중인 실행 컨텍스트가 렉시컬 환경의 상위 스코프이다. 스코프는 this가 있어야 하기 때문에, 렉시컬 스코프가 스코프이다

this는 식별자 역활을 하는 키워드

식별자는 환경 레코드에 있는 것만 식별자다

함수와 그함수의 렉시컬 환경의 조합이다

그 함수는 그 함수 상위를 기억하고 있다.

상태를 안전하게 유지하고 변경하기 위해서 클로저를 사용한다

내부함수보다 외부함수가 오래 살아 남아야하고, 내부함수가 외부함수를 가리켜야한다.

함수가 일급 객체여야 함수프로그램을 만들 수 있어야한다. 함수를 함수를 return 할 수 있어야 한다.

접근 제한자를 이용하여 프로퍼티의 접근을 막는 것이 객체지향(같은 클래스 내부에서만 사용할 수 있다)

클로저는 인스턴스를 1개만들때는 완벽 은닉이 되지만 여러개를 만들때는 빈틈이 있다. 인스턴스를 여러개 만든다면 클래스를 이용하여 private를 이용해야 한다

'ConnecTo' 카테고리의 다른 글

2022/08/24 - TIL  (0) 2022.08.24
2022/08/23 - TIL  (0) 2022.08.23
2022/08/19 - TIL  (0) 2022.08.19
2022/08/18 - TIL  (0) 2022.08.18
2022/08/17 - TIL  (0) 2022.08.17