[JavaScript] var, let, const의 차이(cf. 스코프, 호이스팅)

배고픈 배극곰·2023년 12월 18일
0

기술면접

목록 보기
7/26

목차
1. 변수 생성 과정
2. var, let, const 비교
3. 호이스팅

1. 변수 생성 과정

먼저 변수의 생성 과정에 대해 살펴보려고 한다.

1. 선언 단계

실행 컨텍스트의 변수객체에 등록한다. 즉, 변수명(식별자)을 등록하여 스코프가 참조할 대상을 만든다.

2. 초기화 단계

변수저장을 위해 메모리에 공간을 확보한다. undefined가 할당

3. 할당 단계

undefined로 초기화된 변수에 실제 값을 할당한다.

2. var, let, const 비교

var

1. 함수 레벨 스코프

  • 함수 스코프를 따르기 때문에 함수 내에서 접근하기만 한다면, 다른 모든 블록스코프에서 접근이 가능하므로 의도치 않게 변수가 오염될 수 있다.
  • 즉, 함수 외부에서 생성한 변수는 모두 전역변수인셈.

2. 중복 선언 가능

이미선언한 변수를 의도치 않게 같은 이름으로 선언해도 오류발생X.  알려주지 않으니 문제.

선언단계와 초기화 단계가 동시에 진행.

3. 선언단계와 초기화단계가 동시에 진행된다.

그 뜻은, 변수 선언문 전에 변수에 접근해도 에러가 발생하지 않고 undefined가 출력된다.

(메모리에 공간까지 확보했으니까)

cf. 변수 호이스팅이 가능해서 가능한 일.

console.log(bae);	// undefined	
// 호이스팅이 일어나기 때문에 변수가 선언된 것으로 적용된다.
// => "여기 해당 블록스코프에서 변수 사용할게!" (선언단계)
// => 메모리에 변수 공간 확보 undefined로 초기화(초기화단계)

var bae;
console.log(bae);	// undefined

bae = 1;
console.log(bae);	// 1
// 할당문에 도달해야 할당단계가 실행된다!

[##Image|kage@cOXtEy/btsrtdq9s0W/0TXYhNWeAkwHKYYuuDPW6k/img.png|CDM|1.3|{"originWidth":1016,"originHeight":229,"style":"alignLeft","width":533,"height":120,"caption":"var로 선언된 변수의 생명주기","filename":"var-lifecycle.png"}##]

let 

  1. 블록 레벨 스코프를 따른다.

2. 중복 선언 허용 안함.

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

  var과 달리 let으로 선언된 변수를 변수선언문 이전에 참조하면 referenceError가 발생한다.

  왜?

  let과 const는 TDZ의 영향을 받음.

TDZ(Temporal Dead Zone: 일시적 사각지대)

스코프의 시작 지점부터 초기화 시작 지점까지의 구간.

[##Image|kage@cBKH6Q/btsrq9bJ2At/BwM17KceGD2jqRPbYtAbBK/img.png|CDM|1.3|{"originWidth":931,"originHeight":337,"style":"alignLeft","width":441,"caption":"let으로 선언된 변수의 생명주기","filename":"let-lifecycle.png"}##]

let bae = 1;

if (1) {
	console.log(bae);	// 1이 출력될 것 같지만 => Reference에러가 뜬다.
	let bae = 2;
}

\=> 왜냐하면 bae라는 변수는 이미 전역변수로 선언되었지만, 블록 스코프 안에서 같은이름으로 지역변수가 선언되었기 때문에 블록스코프 시작지점에서 ~~~ 초기화 구간까지 TDZ에 빠진다!

cf. let이나 const로 선언한 변수는 전역 객체의 프로퍼티가 아니다. ( var로 선언한 변수를 전역변수로 쓰면 전역 객체의 프로퍼티가 됨.)

전역변수로 let bae = 2; 선언해도 전역 스코프에 바인딩되어 전역변수가 되는것이지 전역객체에 바인딩이 되지 않는다고 함.

\=> 일반적으로 Browser-side에서의 전역객체는 window객체를 의미함. (server-side즉 node.js에서는 global객체)

const

1. 선언과 초기화를 동시에 진행해야 한다. (재선언, 재할당 불가능)

2. 재할당은 불가능하나, 객체의 내용을 수정할 수는 있다.

  (객체의 프로퍼티는 보호되지 않음.)

cf. 재할당과 수정의 차이

 - 재할당 : 변수에 할당할 값의 메모리 주소를 새롭게 부여.

 - 수정 : 메모리 주소를 참조해 요소를 바꾸는거.

let obj = {
    name: "bae",
    gender: "male",
    age: 27,
    height: 178,
}

//수정
obj.age = 25

//재할당
obj = {
    name: "bae",
    gender: "male",
    age: 25,
    score: 100,
}

★3. 호이스팅

1. 정의

변수, 함수 선언이 스코프 최상단으로 옮긴 것처럼 동작하는 자바스크립트의 특성.

2. 설명

var, const, let 중 어떤 키워드로 변수를 선언하느냐에 따라 호이스팅의 방식이 조금 다르다.

이 내용은 위에서도 다뤘지만 다시 정리하자면,

JS에서 변수 생성은 선언 -> 초기화 -> 할당 단계로 이루어짐.

var - 변수 선언문 이전에 참조하면 undefined가 발생. (호이스팅 특성 + var는 선언단계와 초기화단계가 동시 진행하므로)

let 과 const - 변수는 hoisting되지만, 값은 초기화되지 않는다. (선언단계와 초기화단계가 나눠져 있으므로)

따라서 const와 let으로 선언한 변수를 변수 선언 전에 사용하려고 하면 Reference Error나온다.

이 스코프의 시작지점에서 변수의 선언문까지 구간을 TDZ(Temporal Dead Zone)라고 한다.

결론

기본적으로 변수의 스코프는 최대한 좁게 만드는 것을 권장하므로, var보다는 let과 const를 사용하고,

상수라면 const를 활용하는 것이 바람직하다.

 재할당재선언스코프
varOO함수레벨
letOX블록레벨
constXX블록레벨

참고 : https://poiemaweb.com/es6-block-scope

면접용 답변
=> var은 변수 선언과 초기화 단계가 일어나고, let과 const는 선언단계와 초기화 단계가 나누어져 일어납니다.

profile
마부작침 형설지공

0개의 댓글