본문 바로가기
자바스크립트 (JavaScript)/이론

변수, 호이스팅, TDZ (Temporal Dead Zone) 개념

by Hwanii_ 2023. 8. 20.
728x90

1.

//  var는 한번 선언된 변수를 다시 선언 할 수 있다.

var name = 'mike';
console.log(name);  //  mike

var name = "jane";
console.log(name)   //  jane

 

2.

//  let은 한번 선언된 변수를 다시 선언 할 수 없다.

let name = 'mike';
console.log(name);  //  mike

let name = 'jane';
console.log(name);  //  error !

 

3.

//  var는 선언하기 전에 사용할 수 있다.
//  >> 호이스팅 이라 한다.

console.log(name);  //  undefined.

var name = 'mike';

 

4.

//  var는 선언하기 전에 사용할 수 있다.
//  실제 작동 되는 원리는 아래와 같다.
//  var로 선언한 모든 변수는, 코드가 실제로 이동 하지는 않지만,
//  최상위로 끌어 올려진것처럼 동작 한다.
//  이를, 호이스팅 이라 한다. (hoisting)
//  호이스팅 :
//  스코프 내부 어디서든 변수 선언은 최상위에 선언된 것 처럼 행동.

var name;

console.log(name);  //  undefined.

name = 'mike';

//  이때, console.log(name) 은 undefined 가 뜨게 된다.
//  선언은 호이스팅 되지만,
//  할당은 호이스팅 되지 않기 때문이다.
//  var name; 만 최상위로 올려지고,
//  name = 'mike' 는 이동 하지 않기 때문이다.

 

5.

//  let 으로 선언된 것도 호이스팅은 된다. (const 도 호이스팅이 가능 하다)
//  하지만, 아래의 코드는 ReferenceError 에러가 발생 하게 된다.
//  할당을 하기 전까지는, 사용이 불가능 하다는 의미 이다.

console.log(name);  //  ReferenceError.

let name = 'mike';

 

let으로 선언한 변수를 사용 하려면,

반드시 값이 존재 해야 한다.

 

값이 없기 때문에, ReferenceError 가 발생 하는 것을 확인 할 수 있다.

 

만약 let 이 아니라, var 였으면, undefined 로 뜨게 된다.

 

[ 참고 ]

호이스팅이 되서,

let name; 은 상단으로 올라가게 되는 효과를 가지는데,

name = 'mike'

즉, 할당은 같이 호이스팅 되지 않는다.

 

분명, 선언과 할당을 동시에 하는 초기화 코드를 작성 했지만,

호이스팅은 선언부만 올라가고, 값을 초기화 해주는 부분은 올라 가지 않는다.

 

6.

//  let 으로 선언된 것도 호이스팅은 된다. (const 도 호이스팅이 가능 하다)
//  하지만, 아래의 코드는 ReferenceError 에러가 발생 하게 된다.
//  TDZ(Temporal Dead Zone) 라는 개념이 있다.
//  할당을 하기 전까지는, 사용이 불가능 하다는 의미 이다.

//  ===== TDZ(Temporal Dead Zone) =====
//  console.log(name);
//  ===== TDZ(Temporal Dead Zone) =====

const name = 'mike';    //  함수 선언 및 초기화.

console.log(name);  //  사용 OK.

//  TDZ 의 목적
//  코드를 예측 가능 하게 하고, 잠재적인 에러를 방지 하기 위해서 이다.

 

TDZ(Temporal Dead Zone) 라는 개념이 있다.

 

TDZ는 변수가 선언되었지만 초기화되기 전까지의 구간을 의미 한다.

 

7.

let age = 30;

function showAge() {
    console.log(age);
}

showAge();

//  OK.

 

8.

let age = 30;

function showAge() {
    console.log(age);

    let age = 20;
}

showAge();

//  에러 발생.
//  showAge() 함수 내부는 바깥의 영역과 별개의 영역 이다.
//  따라서, let으로 선언된 age 라는 변수는 별개의 스코프 이다.
//  TDZ 이슈로 인해서, ReferenceError 가 발생 하게 된다.

 

호이스팅 개념 이슈 이다.

 

showAge() 함수 내부에 있는,

let age = 20; 이

호이스팅 개념에 의해서,

let age; 가 상단으로 올라가고,

age = 20; 할당부가 아래에 남게 된다.

 

근데,

 

변수 선언 및 초기화가 동시에 된 형태가 아니라,

 

let age;

console.log(age);

age = 20;

 

으로 되기 때문에, 값이 없어서 에러가 발생하는것이다.

 

위의 코드를 정상적으로 작동 시키려면 아래와 같이 수정 해야 한다.

 

let age = 30;

function showAge() {
    let age = 20;	//	변수 초기화
    console.log(age);	//	20 출력
}

showAge();
console.log(age);	//	30 출력

 

그러면,

함수 내부의 age와 외부의 age가 서로 다른 변수가 되서,

코드가 정상적으로 작동 하게 된다.

 

9.

변수의 생성 과정

 

//  변수의 생성 과정

//  1.  선언 단계
//  2.  초기화 단계
//  3.  할당 단계

//  초기화와 할당의 차이점

//  초기화는 변수를 선언함과 동시에 값을 넣어 주는 것을 의미 한다.
//  예시)
//  var test = 'test1234';

//  할당은 변수를 선언 하고 나서, 대입 연산자 (=) 를 통해 값을 넣어 주는 것을 의미 한다.
//  예시)
//  var test;
//  test = 'test1234';

//  var은 선언과 초기화를 한번에 처리 한다.

//  var
//  1.  선언 및 초기화 단계
//  2.  할당 단계

//  초기화 : undefined를 할당 해주는 단계를 의미 한다.

//  let은 선언 단계와 초기화 단계가 분리 되어 처리 된다.

//  let
//  1.  선언 단계
//  2.  초기화 단계
//  3.  할당 단계

//  const는 선언, 초기화, 할당 단계를 한번에 싹 처리 한다.

//  const
//  1.  선언 + 초기화 + 할당

//  예시)

let name;
name = 'mike';

var age;
age = 30;

const gender;
//  Missing initializer in const declaration 에러.
//  선언 하면서 할당을 바로 안해서 발생 하는 에러.
gender = 'male';

 

10.

스코프 개념

 

//  스코프

//  var : 함수 소코프 (function-scoped)

//  let & const : 블록 스코프 (block-scoped)
//  함수, if 문, for 문, while 문, try/catch 문, .. 등등

//  예시

function add() {
    //  Block-level Scope (지역 변수)
}

let str = 'test';
if (str == 'test') {
    //  Block-level Scope (지역 변수)
}

for (let i = 0; i < 10; i++) {
    //  Block-level Scope (지역 변수)
}

//  예시 2

const age = 30;

if (age > 19) {
    var txt = '성인';
}

console.log(txt);   //  성인

//  if 문 안에 선언 및 초기화 된 var txt는 if 문 밖에서도 사용이 가능 하다.

//  예시 3

const str2 = 'test';

if (str2 == 'test') {
    const str3 = 'test02';
}

//  console.log(str3);

//  변수 str3은 if 문 내부의 지역 변수로 선언 및 초기화 되었기 때문에,
//  if 문 밖에서 사용이 불가능 하다.
//  Block-level Scope

//  예시 4

//  하지만, var도 함수 내부에서 선언 되면 외부 에서 사용이 불가능 하게 된다.
//  var는 if 문, for 문, try-catch 문, .. 등에서 사용 되면,
//  외부에서도 사용이 가능 하지만,
//  유일하게 "함수" 내부에서 선언되면,
//  var, let, const 변수 모두, 외부에서 사용이 불가능 하다.

function add(num1, num2) {
    var result = num1 + num2;
}
    console.log(result);

add(2, 3);

//  변수 선언 뿐만 아니라, 함수 선언도 호이스팅이 된다.
//  그래서, add(2,3); 이 메모리에 올려지게 되서,
//  실제로 코드상 function add(num1, num2) 보다 아래에 있더라도,
//  동작 할 수 있게 된다.

 

var는 if문, for문, try-catch 문, .. 등에서 사용되도,

외부에서 사용이 가능 하지만,

 

유일하게 "함수" 내부에서 선언되면,

제 아무리 var 이여도,

함수 외부에서 사용이 불가능 하다.

 

result가 선언조차도 되어 있지 않아서 발생하는 에러 이다.

 

11.

정리

//  결론

//  var 를 사용 하는것 보다,
//  let과 const를 사용 하는것을 지향 해야 한다.
//  코드를 예측 가능 하게 하고, 잠재적인 에러를 방지 하기 위해서 이다.
//  why ?
//  TDZ == Temporal Dead Zone 개념이 적용 되기 때문 이다.

//  var 변수의 단점
//  1)  중복 선언으로 인해 예기치 못한 값이 반환 될 수 있다.

//  2)  함수가 아닌 다른 블록 스코프 에서 선언된 변수는
//      모두 전역 변수로 취급 되어 예기치 못한 할당이 일어날 수 있다.

//  3)  선언 전에 변수를 참조하면 undefined 가 될 수 있다.

//  위와 같이 3가지 문제가 발생할 수 있으므로,
//  var 변수를 사용하는 것을 지양하고,
//  let & const 변수를 사용하는 것을 지향 해야 한다.
//  상수를 사용 해야 한다면, const 를 사용 하면 된다.
//  Java의 final 키워드와 유사한 역할 이라고 생각 하면 된다.

 

반응형