스코프, 호이스팅

oYJo·2025년 3월 26일

JavaScript

목록 보기
35/52
post-thumbnail

1️⃣ 스코프

✔️스코프 : 변수가 접근할 수 있는 범위

전역 스코프, 지역 스코프

함수 스코프

새로운 함수가 생성될 때마다 새로운 스코프 발생한다

원래 자바스크립트 함수 스코프를 따른다

function a() {
	var secret = '12345';
}
secret; //ReferenceError

블록 스코프

블록 {}이 생성될 때마다 새로운 스코프 형성

let, const 등장으로 블록 스코프 형성 가능

function  loop() { 
	for (let i = 0; i < 5; i++) { 
		console.log(i); // 2, 3, 4
	} 
	console.log('final', i); 
} 
loop(); /* ReferenceError: i is not defined */
  • 반면 for문 내에서 i를 let으로 선언할 경우에는 달라진다.
  • let으로 선언한 순간, 변수i는 for문 내에서만 종속되며, for문 외부에서는 i에 접근할 수가 없다.
  • 스코프가 다르기 때문이다.

✔️var 스코프
전역 범위, 함수 범위로 지정할 수 있음
함수 범위 : var 함수 내에 선언될 때

var a = "a1"; // 전역 범위 
    function newFunction() {
        var b = "b1";
    } // 함수 범위

2️⃣ 호이스팅

인터프리터가 변수, 함수의 메모리 공간을 선언 전에 미리 할당하는 것을 의미한다

✔️var 호이스팅
함수 스코프에서 호이스팅
= 함수 내부 어디에서든 접근 가능하다
변수, 함수 선언이 맨 위로 이동되는 자바스크립트 매커니즘
맨위로 끌어올리는 것처럼

console.log (a);
var a = "a1"
var a;
console.log(a); // a is undefined
a = "a1"

이렇게 변수가 나중에 선언되어도, 자바스크립트는 var변수는 범위 내에 맨 위로 올리면서 해석한다
대신 값은 undefinded로 초기화된다

왜? 자바스크립트의 무슨 특성 때문에?
코드를 순차적으로 한 줄 한 줄 실행하기 전에 소스 코드를 평가하면서
변수 선언문이 먼저 실행되기 때문에 자동으로 var a가 먼저 위로 해석되는 것
❗️이때 실제로 끌어올려지는 것이 아니라, 그렇게 보여지는 것
= 모든 선언문은 런타임 이전 단계에서 먼저 실행되기 때문

✔️let, const 호이스팅
블록 스코프에서 호이스팅된다
하지만 에러가 발생(TDZ 일시적 사각지대)
자바스크립트는 TDZ 접근 허용하지 않는다

let foo = 1;
{
  console.log(foo); // ReferenceError: Cannot access 'foo' before initialization
  let foo = 2;
  // 블록 스코프 안에서 호이스팅이 일어나기 때문에 참조 에러 발생
}
console.log(foo); // 이미 에러가 나서 나오지 않는다

var선언 단계, 초기화 단계가 한번에 이루어진다


스코프에 변수 등록, 메모리에 변수 공간 확보, undefined 초기화
그렇기에 스코프에 변수가 존재하기에 참조 에러가 발생하지 않는다
다만 값이 undfined일 뿐, 그리고 할당문 도달 후에 값이 할당되는 것

하지만, let선언단계, 초기화 단계가 분리되어 있다
그래서 스코프에 변수가 등록은 되지만, 초기화 단계는 변수 선언문에 도달했을 때 이루어져서 참조에러가 이루어진다
변수 초기화가 안 이루어졌으니깐

예시

{
  console.log(name);
  const name = '김바코';
}

// ReferenceError: Cannot access 'name' before initialization
console.log(name);
const name = '김바코';

// ReferenceError: Cannot access 'name' before initialization

두 코드의 차이점은 변수 선언 위치와 호이스팅(hoisting) 때문

✔️TDZ(일시적 사각지대)
선언 전에 발생하는 것이 아니라, 초기화 전에 발생

letconst로 선언된 변수는 스코프의 시작 지점에서 선언되지만,
실제로 초기화되기 전까지는 TDZ에 존재하여 접근할 수 없다

⭐️변수는 선언(Declaration)초기화(Initialization)할당(Assignment) 과정으로 진행되기에



스코프 시작 지점부터 초기화 시작 지점까지의 사각지대 구간
= 선언 단계 ~ 초기화 단계 사이

console.log(myVar); // ReferenceError: Cannot access 'myVar' before initialization
let myVar = 10;
console.log(myVar); // 10
{
    console.log(myVar); // TDZ: 초기화 전에 접근 불가 
// ReferenceError: Cannot access uninitialized variable.
    let myVar = 5; // 선언과 동시에 초기화됨
    console.log(myVar); // 이미 래퍼런스 에러로 나오지 않는다
}

var는 TDZ가 존재하지 않는다

호이스팅 될 때 선언과 함께 초기화 되기 때문에 TDZ가 없다

console.log(myVar); // undefined (호이스팅은 된다)
var myVar = 10;
console.log(myVar); // 10

첫 번째 코드

{
  console.log(name);
  const name = '김바코';
}

// ReferenceError: Cannot access 'name' before initialization
// 초기화 전에 name 접근할 수 없다
  • 이 코드는 블록 스코프 {} 안에서 실행된다

  • const name 변수가 블록 내부에서 선언되었기 때문에, 블록 바깥에서는 보이지 않는다

  • 하지만 호이스팅(hoisting) 때문에 const name블록의 최상단으로 끌어올려지지만, 초기화는 되지 않는다

  • console.log(name);이 실행될 때, nameTDZ(Temporal Dead Zone, 일시적 사각지대)에 있기 때문에 ReferenceError가 발생한다


두 번째 코드

console.log(name);
const name = '김바코';

// ReferenceError: Cannot access 'name' before initialization
  • const name선언되기도 전에 접근하려고 했기 때문에 ReferenceError: Cannot access 'name' before initialization 오류가 발생한다

  • constlet호이스팅되지만 TDZ(일시적 사각지대)에 걸려 있어서 선언 전에 접근할 수 없다

  • var였다면 undefined가 출력되지만, constlet은 TDZ 때문에 오류가 발생한다

결론

  1. TDZ(일시적 사각지대): constlet은 선언 전에 접근할 수 없음 → ReferenceError 발생

  2. 블록 스코프: {} 내부에서 선언된 변수는 바깥에서 접근할 수 없음

  3. 호이스팅: constlet은 호이스팅되지만 초기화되지 않아서 선언 전 접근 시 오류 발생

↑ 해결하려면 변수를 선언 후에만 사용해야 한다

profile
Hello! My Name is oYJo

0개의 댓글