Skip to content

Latest commit

 

History

History
175 lines (125 loc) · 6.17 KB

File metadata and controls

175 lines (125 loc) · 6.17 KB

13.1 스코프란?

  • 모든 식별자(변수 이름, 함수 이름, 클래스 이름 등)는 자신이 선언된 위치에 의해 다른 코드가 식별자 자신을 참조할 수 있는 유효 범위가 결정되는데, 이를 스코프라고 한다. ex) 매개변수의 "스코프"가 함수 몸체 내부로 한정됨
  • 자바스크립트 엔진이 식별자를 검색할 때 사용하는 규칙

⚠️ 변수 중복 선언

  1. var로 선언된 변수는 같은 스코프 내에서 중복 선언이 허용됨.
function foo() {
  var x = 1;
  // var로 선언된 변수는 같은 스코프 내에서 중복 선언을 허용함
  // 자바스크립트 엔진에 의해 var 키워드가 없는 것처럼 동작함
  var x = 2;
  console.log(x); // 2
}
foo();
  1. let이나 const로 선언된 변수는 같은 스코프 내에서 중복 선언을 허용하지 않는다.
function bar() {
  let x = 1;
  // let이나 const로 선언한 변수는 같은 스코프 내에서 중복 선언을 허용하지 않음
  let x = 2; // SyntaxError
}
bar();

13.2 스코프의 종류

스코프 종류 설명
전역 스코프 (Global Scope) 코드 어디서든 접근 가능
함수 스코프 (Function Scope) 함수 내부에서만 접근 가능
블록 스코프 (Block Scope) {}(중괄호) 내부에서만 접근 가능 (let, const)
모듈 스코프 (Module Scope) import와 export를 사용하여 모듈 단위로 관리
  • 전역: 코드의 가장 바깥 영역
  • 지역: 함수 몸체 내부

13.2.1 전역과 전역 스코프

전역 변수는 어디서든지 참조 가능하다. 함수 내부에서도 참조 가능하다.

13.2.2 지역과 지역 스코프

지역이란 함수 몸체 내부를 말한다. 지역 변수는 자신의 지역 스코프와 하위 지역 스코프에서만 유효하다.

13.3 스코프 체인

스코프가 함수의 중첩에 의해 계층적 계층을 갖는 것을 의미함 스코프가 계층적으로 연결된 것을 스코프 체인이라고 한다. 변수를 참조할 때 자바스크립트 엔진은 스코프 체인을 통해 변수를 참조하는 코드의 스코프에서 시작하여 상위 스코프 방향으로 이동하며 선언된 변수를 검색한다.

let globalVar = "전역 변수";

function outer() {
  let outerVar = "외부 함수 변수";

  function inner() {
    let innerVar = "내부 함수 변수";
    console.log(innerVar); // "내부 함수 변수" (가장 가까운 스코프)
    console.log(outerVar); // "외부 함수 변수" (한 단계 위의 스코프)
    console.log(globalVar); // "전역 변수" (더 위의 스코프)
  }

  inner();
}

outer();
  1. 현재 스코프에서 찾음
  2. 없으면 한 단계 상위 스코프로 이동(렉시컬 스코프)
  3. 그래도 없으면 계속 올라가다가 전역 스코프에서 찾음
  4. 전역에서도 없으면 ReferenceError 발생

❓렉시컬 스코프란:

  • 스코프 체인은 컨텍스트의 렉시컬 환경을 단방향으로 연결한 것이다.
  • 전역 렉시컬 환경은 코드가 로드되면 바로 생성되고 함수의 렉시컬 환경은 함수가 호출되면 바로 생성됨.

13.3.1 스코프 체인에 의한 변수 검색

상위 스코프에서 유효한 변수는 하위 스코프에서 자유롭게 참조 가능하지만, 하위 스코프에서 유효한 변수를 상위 스코프에서 참조할 수 없다. (상속 개념)

13.3.2 스코프 체인에 의한 함수 검색

스코프 == "식별자를 검색하는 규칙"

13.4 함수 레벨 스코프

  • 함수 내부에서 선언된 변수는 함수 내부에서만 접근 가능하고, 함수 바깥에서는 접근할 수 없는 스코프

  • 자바스크립트에서는 var 키워드로 선언한 변수만 함수 레벨 스코프를 가짐. 즉, var로 선언된 변수는 오직 해당 함수 안에서만 유효하며, 블록 {}을 무시하고 함수 전체를 스코프로 가짐.

13.5 렉시컬 스코프

  • 자바스크립트는 렉시컬 스코프를 따른다.
  • 함수를 어디서 정의했는지에 따라 상위 스코프를 결정한다. (정적으로 결정됨)
    • 함수가 호출된 위치는 상위 스코프 결정에 아무런 영향을 주지 않는다.
  • 함수 호출될 때마다 함수의 상위 스코프를 참조하기 위해 함수 객체는 상위 스코프를 기억해둔다.

✅ 1. 함수 레벨 스코프 예제 (var 사용)

function myFunction() {
  var functionScopedVar = "나는 함수 레벨 변수";
  console.log(functionScopedVar); // ✅ 함수 내부에서 접근 가능
}

myFunction();
console.log(functionScopedVar); // ❌ ReferenceError: functionScopedVar is not defined
  • 함수 내부에서 선언된 var 변수는 함수가 끝나면 사라짐!
  • 함수 바깥에서는 functionScopedVar에 접근할 수 없음.

✅ 2. 함수 레벨 스코프가 문제가 될 수 있는 상황

  1. var는 블록{}을 무시하기에, 의도치 않게 변수 덮어쓰기 문제 발생 가능
function varScopeIssue() {
  var x = 1;

  if (true) {
    var x = 2; // ❗ 같은 변수 `x`가 다시 선언됨 (블록 무시)
  }

  console.log(x); // 2 (함수 전체에서 같은 변수로 취급)
}

varScopeIssue();
  1. for 루프에서 var 사용 시 문제 => var는 함수 레벨 스코프라서 for 블록을 무시하고, 최종적으로 i = 3이 되어버림
for (var i = 0; i < 3; i++) {
  setTimeout(() => console.log(i), 1000);
}
// ❌ 예상: 0, 1, 2
// ❗ 실제 출력: 3, 3, 3 (모든 `setTimeout`이 같은 `i`를 참조)

====

for (let i = 0; i < 3; i++) {
  setTimeout(() => console.log(i), 1000);
}
// ✅ 올바른 출력: 0, 1, 2 (각 `i`가 블록 스코프 유지)

✅ 3. 함수 레벨 스코프를 피하는 방법

  1. let, const와 같은 블록 레벨 스코프 적용
  2. IIFE(즉시 실행 함수) 사용
(function () {
  var secret = "비공개 변수";
  console.log(secret); // ✅ "비공개 변수"
})();

console.log(secret); // ❌ ReferenceError: secret is not defined