2차_2주차_이나영_회고록 - hyeone999/Docs-JS_deepDive_Study GitHub Wiki
23장 실행 컨텍스트
1. 소스코드의 타입
소스코드 타입 | 설명 |
---|---|
전역 코드 | 전역에 정의된 코드. 함수 내부 코드는 포함되지 않음 |
함수 코드 | 함수 내부에 정의된 코드 |
eval 코드 | eval() 로 실행되는 코드 |
모듈 코드 | 모듈 내부에 정의된 코드 (모듈 스코프 가짐) |
2. 평가와 실행
평가
- 실행 컨텍스트 생성
- 변수/함수 선언 → 스코프에 등록
실행
- 등록된 식별자 참조 → 코드 실행
- 실행 결과 → 다시 스코프에 저장
var x; // 평가
x = 1; // 실행
3. 실행 컨텍스트란?
코드 실행에 필요한 환경 정보 객체
- 스코프 관리 (식별자 등록 및 검색)
- 실행 순서 제어
4. 실행 컨텍스트 스택
실행 컨텍스트는 스택(LIFO) 구조로 관리됨
function foo() {
function bar() {
console.log("Hi");
}
bar();
}
foo();
순서 | 컨텍스트 |
---|---|
1 | 전역 |
2 | foo |
3 | bar |
5. 렉시컬 환경
식별자와 상위 스코프 참조를 저장하는 구조
구성 요소
- 환경 레코드: 변수, 함수, 매개변수 저장
- 외부 참조: 상위 렉시컬 환경을 가리킴
6. 실행 흐름 예시
var x = 1;
const y = 2;
function foo(a) {
var x = 3;
const y = 4;
function bar(b) {
const z = 5;
console.log(a + b + x + y + z);
}
bar(10);
}
foo(20); // 42 출력
식별자 | 참조 위치 |
---|---|
a | foo 매개변수 |
b | bar 매개변수 |
x, y | foo 내부 변수 |
z | bar 내부 변수 |
7. 전역 렉시컬 환경 구성
전역 환경 레코드
var
, 함수 선언문 → 전역 객체(window)let
,const
→ 선언적 환경 레코드 (TDZ 존재)
this 바인딩
- 전역에서는 this → 전역 객체(window)
요약
항목 | 설명 |
---|---|
실행 컨텍스트 | 코드 실행 환경 객체 |
실행 컨텍스트 스택 | 코드 실행 순서 관리 |
렉시컬 환경 | 스코프와 식별자 저장소 |
스코프 체인 | 외부 참조 연결 구조 |
this 바인딩 | 실행 위치에 따라 결정됨 |
24장 클로저
1. 렉시컬 스코프
함수가 정의된 위치에 따라 상위 스코프가 결정됨
- 상위 스코프는 함수가 정의될 때 저장됨 (
[Environment](/hyeone999/Docs-JS_deepDive_Study/wiki/Environment)
) - 함수 호출 위치와 무관
[Environment](/hyeone999/Docs-JS_deepDive_Study/wiki/Environment)
2. 함수 객체의 내부 슬롯 - 함수는 정의될 때의 렉시컬 환경을 저장함
- 이는 함수 실행 시 상위 스코프 참조에 사용됨
3. 클로저란?
함수 + 함수가 선언된 렉시컬 환경의 조합
function outer() {
const x = 10;
return function inner() {
console.log(x);
};
}
const innerFunc = outer();
innerFunc(); // 10
특징
항목 | 설명 |
---|---|
생존 시간 | 외부 함수보다 오래 존재 |
기억 | 외부 렉시컬 스코프 기억 |
접근 가능 | 외부 함수 지역 변수 접근 가능 |
GC 제외 | 참조 중이면 메모리 해제되지 않음 |
4. 클로저 활용
전역 변수 사용 문제
let num = 0;
function increase() {
return ++num;
}
클로저로 은닉
const increase = (function () {
let num = 0;
return function () {
return ++num;
};
})();
다중 메서드 구성
const counter = (function () {
let num = 0;
return {
increase() { return ++num; },
decrease() { return num > 0 ? --num : 0; },
};
})();
고차 함수와 클로저
function makeCounter(aux) {
let counter = 0;
return () => (counter = aux(counter));
}
function increase(n) { return ++n; }
function decrease(n) { return --n; }
const inc = makeCounter(increase);
const dec = makeCounter(decrease);
5. 클로저와 상태 공유
const counter = (function () {
let counter = 0;
return function (aux) {
counter = aux(counter);
return counter;
};
})();
- 하나의 상태를 여러 함수가 공유
- 보조 함수로 상태 변경 위임
6. 정보 은닉 (캡슐화)
생성자 함수 클로저 활용
function Person(name, age) {
this.name = name;
let _age = age;
this.sayHi = function () {
console.log(`${this.name}, ${_age}`);
};
}
즉시 실행 함수 사용 (단점: 상태 공유)
const Person = (function () {
let _age = 0;
function Person(name, age) {
this.name = name;
_age = age;
}
return Person;
})();
7. ES6 private 필드 문법
class Person {
#age;
constructor(name, age) {
this.name = name;
this.#age = age;
}
sayHi() {
console.log(`${this.name}, ${this.#age}`);
}
}
요약
항목 | 설명 |
---|---|
렉시컬 스코프 | 정의 위치 기준으로 스코프 결정 |
클로저 | 함수 + 정의 당시 스코프 기억 |
활용 | 상태 은닉, 공유, 캡슐화 |
ES6 문법 | private 필드(# )로 완전 은닉 가능 |
느낀점
자바 스크립트 공부 중 가장 어려웠던 부분이었다. 이해도 오래걸렸고 좀 더 심도깊은 이야기라 반복해서 공부를 해야할 부분같다. 호이스팅이나 스코프 부분을 좀 더 확실하게 하면 이해하는 데 문제는 없을 수도 있겠다라고 생각을 했다.