[Javascript] var, let, const의 차이점을 알아보자

블루·2022년 9월 11일
0

슬라임

JS 기초문법부터 열심히(?) 공부해 현재는 react.js, next.js, typescript를 공부하고 있습니다. 개발을 하다가 문득 이런 생각이 들었습니다. 면접 상황에서 면접관님이 var, let, const의 차이를 설명하라고 하면 나는 명쾌하게 대답할 수 있는가? 전체적인 메커니즘은 생각이 났지만, 이것을 설명하라고 하면 못할 것 같았습니다. 개발을 하며 밥먹듯이 하는것이 변수 선언인데, 개발을 하며 밥 먹듯이 하는 것이 변수 선언인데, 이마저도 제대로 이해하고 있지 못하다니...😭
그래서 이번 기회에 제대로 정리해보고자 합니다.


var에 관한 이야기

es5 이전에는 var이 변수를 선언하는 유일한 방법이었습니다. 하지만 es6에서 let과 const가 등장하여 var은 잘 사용하지 않게 되었습니다. 어떤 이유로 var이 let과 const로 대체되었는지, var의 문제점(단점)에 대해 설명해보겠습니다.

var의 문제점 1. 변수 중복 선언이 가능하다

var A = 'brother';
var A = 'sister';

console.log(A);	// sister 출력

위 코드와 같이 var은 중복 선언이 가능합니다.


var의 문제점 2. 함수 레벨 스코프를 가진다

var A = 'brother';

if(true) {
  var A = 'sister';
}

console.log(A);	// sister 출력

위 코드와 같이 var은 블록 레벨 스코프가 아닌, 함수 레벨 스코프를 가집니다. 만약 블록 레벨 스코프를 가졌다면 위 코드에서는 brother가 출력되어야합니다.


var의 문제점 3. 변수 호이스팅이 발생할 때 변수가 undefined로 초기화된다.

var A;

console.log(A);	// undefined 출력
console.log(B);	// undefined 출력

var B = 'brother';

위 코드와 같이 var 변수가 호이스팅이 발생하면 변수가 undefined로 초기화됩니다. 위 코드에서 A의 경우 값이 할당되지 않은 변수를 출력하도록 했으므로 undefined가 출력됩니다. B의 경우 호이스팅에 의해 초기화된 변수를 출력하도록 했으므로 undefined가 출력됩니다.


let과 const에 관한 이야기

이번에는 let과 const에 대해 이야기해보도록 하겠습니다. 위의 var과 어떤점이 다른지, 또 let과 const는 어떤점이 다른지에 대해서 설명해보겠습니다.

var과의 차이 1. 변수 중복 선언이 불가하다

let A = 10;
let A = 20;	// error 발생 

var과 다르게 let과 const는 변수 중복 선언이 불가합니다.


var과의 차이 2. 블록 레벨 스코프를 가진다

let A = 'brother';

if(true) {
  let A = 'sister';
}

console.log(A);	// brother 출력

이전의 코드에서 변수 선언 방식을 var에서 let으로 바꿔주었습니다. var 방식에서는 sister가 출력되었지만, let 방식에서는 블록 레벨 스코프를 가지므로 brother가 출력되는 것을 확인할 수 있습니다.


var과의 차이 3. 변수 호이스팅이 발생할 때 변수가 초기화되지 않는다

let A;

console.log(A);	// undefined 출력
console.log(B);	// error 발생

let B = 'brother';

이전 코드에서 변수 B가 undefined가 출력된 것과 다르게 let으로 변수를 선언하면 에러가 발생합니다. 호이스팅 발생 시, undefined로 초기화되지 않기 때문에 초기화되지 않은 변수를 참조하여 참조 에러(Reference Error)가 발생합니다.


TDZ 구간이란?

let, const와 var의 호이스팅 시 차이를 더 자세히 알아봅시다. let, const 키워드로 선언된 변수는 스코프의 시작에서 변수 선언까지 일시적 사각지대(TDZ)에 빠집니다. let, const 키워드로 선언된 변수는 선언 단계와 초기화 단계가 분리되어 진행됩니다. 변수 선언은 var과 똑같이 가장 위에서 실행되지만 초기화는 변수 선언문이 도달하였을 때 이루어집니다. 초기화 이전에 변수에 접근하려고 하면 변수를 위한 메모리 공간이 아직 확보되지 않았기 때문에 참조 에러(Reference Error)가 발생합니다. 따라서 스코프의 시작 지점부터 초기화 시작 지점까지 변수를 참조할 수 없습니다. 스코프의 시작 지점부터 초기화 시작 지점까지의 구간을 '일시적 사각지대(Temporal Dead Zone: TDZ)'라고 부릅니다.
TDZ


let과 const의 차이

이제까지 var과 let, const의 차이를 알아봤으니, 이젠 let과 const의 차이를 알아보도록 하겠습니다.

let A = 10;
A = 20;

const B = 'hello';
B = 'hi';	// error 발생

let 키워드로 변수를 선언하면 변수 재할당이 가능하지만, const 키워드로 변수를 선언하면 변수 재할당이 불가합니다. const는 변수를 상수 취급합니다.


헷갈렸던 상황 1

var funcs = [];

for (var i = 0; i < 3; i++) {
  funcs.push(function () { console.log(i); });
}

for (var j = 0; j < 3; j++) {
  funcs[j]();
}

글 작성을 위해 자바스크립트 변수를 공부하던 중 이 코드를 접하게 되었다. 나는 당연히 결과가 0, 1, 2가 출력될 것이라고 생각했지만, 2, 2, 2가 출력되었다. 그 이유는 var이 함수 레벨 스코프이므로 for 루프 에서 i가 전역 스코프를 가져서 2, 2, 2가 출력된 것입니다. 0, 1, 2가 출력되게 해주려면 다음과 같이 바꾸면 됩니다.

const funcs = [];

for (let i = 0; i < 3; i++) {
  funcs.push(function () {
    console.log(i);
  });
}

for (var j = 0; j < 3; j++) {
  funcs[j]();
}

for 루프에서 i의 선언을 var에서 let으로 바꿔주면 블록 레벨 스코프를 가지게 되므로 0, 1, 2가 출력되게 됩니다.


헷갈렸던 상황 2

let foo = 1;

{
  console.log(foo);
  let foo = 2;
}

1이 출력될 것이라고 예상했지만, 결과는 참조 오류가 발생했습니다. 블록 내에서 let 키워드로 선언된 foo 변수가 호이스팅이 발생하여 TDZ 구간에서 변수를 참조하려 했기 때문에 오류가 발생한 것입니다.


헷갈렸던 상황 3

import React from 'react';
import {View, StyleSheet} from 'react-native';
import Something from './container/Something';

const App = () => {
  return (
    <View style={styles.block}>
      <Something />
    </View>
  );
};

const styles = StyleSheet.create({
  block: {
    display: flex;
    justifyContent: 'center',
    alignItems: 'center',
  },
});

export default App;

react native 관련 코드를 작성하던 도중 문득 이런 생각이 들었습니다. styles 변수는 App 함수 아래에서 선언되었는데 어떻게 App 함수 안에서 사용될 수 있는 것일까? 그 이유는 styles 변수가 App 함수 아래에서 선언되었지만, App 함수는 styles 변수가 읽힌 후 호출되므로 문제 없이 동작한다는 것이었습니다. 아래의 코드로 확인해봅시다.

const A = () => {
  x = 5
  console.log(x)
}

A()	// error 발생

let x = 10

A()	// 5 출력

처음 A 함수를 호출했을 때는 아직 변수 x가 초기화 되지않았기 때문에 에러가 발생합니다. 하지만 두번째로 A 함수가 호출되었을 때에는 x의 값이 할당된 상태이므로 에러가 발생하지 않습니다.




참고자료
https://www.howdy-mj.me/javascript/var-let-const/
https://paperblock.tistory.com/42
https://poiemaweb.com/es6-block-scope
https://oysu.tistory.com/70

profile
개발 일지를 작성합니다

0개의 댓글

관련 채용 정보