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. 렉시컬 환경

식별자와 상위 스코프 참조를 저장하는 구조

구성 요소

  1. 환경 레코드: 변수, 함수, 매개변수 저장
  2. 외부 참조: 상위 렉시컬 환경을 가리킴

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))
  • 함수 호출 위치와 무관

2. 함수 객체의 내부 슬롯 [Environment](/hyeone999/Docs-JS_deepDive_Study/wiki/Environment)

  • 함수는 정의될 때의 렉시컬 환경을 저장함
  • 이는 함수 실행 시 상위 스코프 참조에 사용됨

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 필드(#)로 완전 은닉 가능

느낀점

자바 스크립트 공부 중 가장 어려웠던 부분이었다. 이해도 오래걸렸고 좀 더 심도깊은 이야기라 반복해서 공부를 해야할 부분같다. 호이스팅이나 스코프 부분을 좀 더 확실하게 하면 이해하는 데 문제는 없을 수도 있겠다라고 생각을 했다.