[면접 준비 #1] var, let, const?

Soozynn·2022년 6월 12일
0

면접준비

목록 보기
1/5

var (ES6 이전 자바스크립트에서 사용): 지양

  • 한 번 선언된 변수를 다시 선언할 수 있다 -> 재선언 가능
	var name = "Mike";
	console.log(name); // Mike

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

보통의 일반적인 언어라면 같은 이름을 가진 변수를 재선언하는 것은 불가능하다.
하지만 var는 이조차도 가능하다. 현재 코드에서는 name이 두번 선언된 것을 한 눈에 알 수 있지만 첫 번째 선언부와 두 번째 선언부 사이에 방대한 코드가 있다면 어떻게 될까?

이런 변수의 중복 선언 허용은 의도하지 않은 변수의 변경이 일어날 가능성이 높다.


  • 재할당 가능 (선언문 (var) 없이 변수명만으로 다시 값을 할당 하는 것)
	var name = "Mike";
	console.log(name); // Mike

	name = "Jane";
	console.log(name); // Jane


아래 예시를 보면 선언되기 이전에 콘솔을 출력하지만 error가 나지않고, undefined를 출력한다.

	console.log(name); // undefined
	var name = "Mike"; //

이는 위 코드가 아래와 같은 방식으로 동작하기 때문이다.

var name; // 호이스팅

console.log(name); // undefined
name = "Mike";

let (ES6)

  • 재선언 불가(SyntaxError), 재할당 가능
let name = "sujin";
let name = "suji"; // error 재선언 불가

name = "suji"; // 재할당은 가능

같은 변수를 같은 함수나 블록 스코프 안에서 다시 선언하려고 시도하면 SyntaxError가 발생.


const (ES6)

  • 재할당, 재선언 불가
// 상수의 의미를 지닌 const는 말 그대로 고정된 값(변하고 싶지 않은 값)이다
// 때문에 재할당 재선언이 불가능하여 그 자리에서 값을 할당해주어야한다.

const COLOR_NAME = "color";

const COLOR_NAME = "blue"; // error
COLOR_NAME = "red" // error


🤔 세 변수 모두 호이스팅이 일어나지만, let 과 const 는 왜 var처럼 행동하지 않을까?

  • 바로 Temporal Dead zone (TDZ) 일시적인 사각지대 때문이다!

    TDZ(Temporal Dead Zone)란,
    스코프의 시작 지점부터 초기화 시작 지점까지의 구간을 말한다.

    "시간상" 사각지대인 이유는, 사각지대가 코드의 작성 순서(위치)가 아니라 코드의 실행 순서(시간)에 의해 형성되기 때문.

letconsttdz로 인해 할당을 하기 전에는 사용할 수가 없는 것.
이는 코드를 예측가능하게 하고 잠재적인 버그를 줄일 수 있게 해줌.

호이스팅은 스코프 단위로 일어난다. 때문에 아래와 같은 예제에서는 에러가 난다.

// ❌
let age = 30;

function showAge() {
	console.log(age);
	let age = 20; // 현재 줄의 let이 호이스팅이 일어난다.
}

showAge();

호이스팅은 스코프 단위로 일어난다.
위 예제에서 스코프는 showAge 함수 내부이기 때문에 age를 재선언하는 구문에서 호이스팅이 일어나 에러가 발생하게 된다. 더 자세한 부분은 아래에 적어두었다.


변수의 생성과정 -> 3단계

1. 선언 단계(Declaration phase) : 변수를 실행 컨텍스트의 변수 객체에 등록하는 단계를 의미.
이 변수 객체는 스코프가 참조하는 대상이 됩니다.

2. 초기화 단계(Initialization phase) : 실행 컨텍스트에 존재 하는 변수 객체에 선언 단계의 변수를 위한 메모리를 만드는 단계.
이 단계에서 할당된 메모리에는 undefined로 초기화 됩니다.

3. 할당 단계(Assignment phase) : 사용자가 undefined로 초기화된 메모리의 다른 값을 할당하는 단계.

var

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

초기화: undefined를 할당 해주는 단계

🌈 선언과 초기화 단계가 동시에 일어남
때문에 할당 전에 호출하게 되면 에러를 내지 않고 undefined가 출력되는 것.

let

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

var와 달리 선언 단계와 초기화 단계분리되어 진행.

시간상 사각지대 (TDZ)

let 변수 초기화하기 전에는 읽거나 쓸 수 없음 (선언 구문에 초기 값을 지정하지 않은 경우 undefined로 초기화함). 초기화 전에 접근을 시도하면 ReferenceError가 발생.

호이스팅 되면서 선언 단계가 이루어지지만, 초기화 단계는 실제 코드에 도달했을 때 되기 때문에 var와 달리 할당 전에 호출하게 되면 레퍼런스 에러가 발생하는 것.

console.log(a); // ReferenceError: Cannot access "a" before initialization
let a = 1;
console.log(a);

const

  1. 선언 + 초기화 + 할당

const 는 말 그대로 상수 즉, 변하지 않는 값을 일컫으므로 선언과 동시에 초기화와 할당이 일어난다. const 키워드를 사용하여 선언한 값은 두번 다시 변경할 수 없다는 뜻이다.

"TDZ 구간에 있는 변수 객체"는
선언은 되어있지만 아직 초기화가 되지않아 변수에 담길 값을 위한 공간이 메모리에 할당되지 않은 상태이다.


이때 해당 변수에 접근을 시도하면 Cannot access '%' before initialization 에러 메세지를 만나게된다.
즉, 변수 스코프의 맨 위에서 변수의 초기화 완료 시점까지의 변수"시간상 사각지대"(Temporal Dead Zone, TDZ)에 들어간 변수라고 표현합니다.


변수 Scope

var

  • 함수 스코프 (function-scoped)
    함수 내에서 선언한 변수만 그 지역 변수가 되는 것. 나머지는 다 전역 변수로 올려버리는 문제.
var a = 2;

function foo() {
	var boo = "boo";
}

console.log(a) // 2
console.log(boo) // error, boo is not defined 

위에서 말했듯이 var는 함수 스코프를 가지기 때문에 함수 내 변수는 지역변수가 되어 전역에서 접근이 불가능하다. 하지만 아래와 같은 예시에서는 어떻게 될까?

for (var i =0; i < 5; i++) {
	console.log(i); // 0 1 2 3 4 출력
}

console.log(i);  // 0 1 2 3 4 5

위 예시는 원래는 말이 되지 않는 문법이다. for문 블록 스코프 내에서 선언한 변수이기 때문에 출력이 되지 않는 것이 맞지만 출력이 된다. var는 함수 스코프를 가지기 때문이다. 이 외의 블록 스코프에서는 모두 전역 변수처럼 사용을 할 수가 있는 것.

let, const

  • 블록 스코프 (block-scoped): 함수, if문 for문, while문, try/catch 문 등
    모든 코드 블록 내에서 선언된 변수는 코드 블록 내에서만 유효하며 외부에서는 접근할 수 없다.
    즉, 내부에서 선언한 변수는 지역변수이다.

다시 한번, 위에서 보았던 예제를 변수 생성과정tdz 개념에 빗대어 요약해보자면

// ❌
let age = 30;

function showAge() {
	console.log(age);
	let age = 20; // 현재 줄의 let이 호이스팅이 일어난다.
}

showAge();

let 으로 선언된 변수는 var 키워드와는 다르게 선언단계와 초기화 단계가 분리되어서 진행이 된다. 그렇기 때문에 실행 컨텍스트에 변수를 등록(선언)했지만, 메모리가 할당이 되질 않아(초기화) 접근할 수 없어 참조 에러(ReferenceError)가 발생하는 것 이고,

때문에 우리는 이것을 보고 letconst가 호이스팅이 되질 않는다!! 라고 오해할 수 밖에 없었던 것!

let과 const키워드는 var키워드처럼 호이스팅(hoisting)이 일어난다!

다만, 변수 생성과정에 차이tdz 에 의해 우리에 눈으로는 호이스팅이 일어나지 않는 것처럼 보일 뿐이다.


MDN) let과 const로 선언한 변수도 호이스팅 대상이지만, var와 달리 호이스팅 시 undefined로 변수를 초기화하지는 않는다. 따라서 변수의 초기화를 수행하기 전에 읽는 코드가 먼저 나타나면 에러가 발생.


참고 자료) 코딩앙마 / 누구나 블로그
https://evan-moon.github.io/2019/06/18/javascript-let-const/

0개의 댓글