Chapter 13 스코프

Scope

13.1 스코프란?

  • 유효범위
  • 식별자가 유효한 범위 (선언된 위치에 의해)
  • aka 식별자를 검색할 때 사용하는 규칙 (결정)
    • ex: 여러 x 변수 중 어떤 x를 사용할지 결정
  • 동일한 식별자여도 스코프가 다르면 다른 변수로 취급

    • \(\rightarrow\) 스코프 개념이 존재하기 때문에 변수명이 겹쳐도 괜찮다
    • ex: 폴더+파일 예시- 동일 파일명이라도 폴더가 다르면 다른 파일로 인식
  • var: 함수레벨 스코프, 같은 스코프 내에 중복 선언 허용
    • ⚠️ 의도치 않게 변수값 재할당되는 부작용
  • let, const: 블록레벨 스코프, 같은 스코프 내에 중복 선언 불가
    • 중복 선언 시 SyntaxError 발생

13.2 스코프의 종류

  • 전역 스코프 (Global Scope)

    • 코드 어디서든 참조 가능
    • 최상위 스코프
  • 지역 스코프 (Local Scope)

    • 함수 스코프: 함수 몸체 내부
    • 블록 스코프: 중괄호 내부

13.3 스코프 체인

  • 계층적 구조, 스코프 체인
  • 변수 참조하는 코드의 스코프에서 시작해서 상위 스코프로 이동
  • 실체로 존재함!!!
  • JS Engine에 Lexical Environment가 특정 자료구조를 사용하여 스코프 체인 관리
    • 렉시컬 환경: 실행 컨텍스트의 렉시컬 환경을 단방향으로 연결 (chaining)
  • 상속과 유사함
  • 변수 뿐만이 아니라 함수도 스코프 체인에 묶임

📌 스코프: 식별자를 검색하는 규칙!

13.4 함수 레벨 스코프

  • var : 코드블록이 아니라 함수 내에서 스코프 생김
  • 코드 블록: { }로 묶인 코드 (if, for, while…)

    var x = 1;
    if (true) {
      var x = 10;
    }
    console.log(x); // 10
    
    var i = 10;
    for (var i = 0; i < 5; i++) {
      console.log(i); // 0 1 2 3 4
    }
    console.log(i); // 5
    
    • 🛑 의도치 않은 변수의 값이 재할당

13.5 블록 레벨 스코프

  1. dynamic scope: 실행 시점에 따라 스코프 결정 (어디서 호출)
    • 호출되는 시점에 동적으로 상위 스코프를 결정
  2. lexical scope: 선언 시점에 따라 스코프 결정 (어디서 정의)
    • aka static scope
    • JS 포함 대부분 언어가 lexical scope 사용
var x = 1;

function foo() {
  var x = 10;
  bar();
}

function bar() {
  console.log(x); // 1
}

foo(); // 1, 동적 scope라면 10이었을 것 (foo에서 호출했으므로)
bar(); // 1

2회독 노트


  • 하나의 값은 유일한 식별자에 연결 (Name binding) 되어야 함. 같은 스코프 내에 같은 이름의 식별자 존재하면 안됨
  • 스코프는 네임스페이스이다
    • A namespace provides a container to hold things like functions, classes and constants as a way to group them together logically and to help avoid conflicts.
  • JS 는 다른 언어와 다르게 function-level scope 만 생성함 (var)
    • 하지만 ES6에서 공개된 constlet은 block level scoping을 지원
  • \(Q\). block level 을 지원하기 시작했는데, var은 선언 시 scope가 block이면 무시하고 그 위가 global 또는 function-level 일때까지 타고 올라가서 등록하는걸까?

    if (true) { // 여기서 block scope 생성 (SCOPE B)
      let x = 10; // SCOPE B 내에서 선언된 변수
      const y = 20; // SCOPE B 내에서 선언된 변수
      var z = 30; // GLOBAL SCOPE 에 생성된 변수?
      console.log(x); // 10
      console.log(y); // 20
      console.log(z); // 30
    }
    
    console.log(x); // ReferenceError: x is not defined 
    console.log(y); // ReferenceError: y is not defined
    console.log(z); // 30
    
    • GPT 답변: 네, 정확히 이해하셨습니다! var는 block-level scope를 무시하고, 가장 가까운 function-level 또는 global scope에 변수를 등록합니다. 이 경우 var z는 if 블록을 무시하고 Global Scope에 바인딩됩니다.