일지/JavaScript

[JavaScript] var, let, const 차이점

닉닉눅 2022. 11. 11. 14:34
728x90
반응형

<JavaScript>

프로그래머스 문제를 풀면서 var을 사용하는 사람도 있고 let를 사용하는 사람이 있어 var과 let 추가로 const의 변수 선언 방식의 차이점이 궁금하여 조사했다.

# 변수 선언 방식

1. var -  중복 선언 가능 / 재할당 가능

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

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

var은 동일한 변수명으로 중복 선언이 가능하며, 마지막의 할당된 값이 변수에 저장된다.

위의 코드를 보면 에러가 발생하지 않고 다른 값이 출련된다.

 

이런 var의 특징은 간단한 테스트, 작은 프로젝트에서는 괜찮을 수 있겠으나, 코드량이 많아지는 프로젝트에서는 기존의 선언한 코드를 잊고 값을 재할당하여 꼬이는 문제와 코드량이 많아져 같은 이름의 변수명이 여러번 선언되었다면 문제가 발생하는 위치를 파악하는데 어려움이 생긴다.

 

2. let -  중복 선언 불가능 / 재할당 가능

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

let name = 'second';
console.log(name);
// Uncaught SyntaxError: Identifier 'name' has already been declared

name = 'third';
console.log(name); // third

 

let은 해당 변수가 이미 선언되었다는 에러 메시지가 출력되며, 중복 선언이 불가능하다.
name = 'third' 와 같이 변수 선언 및 초기화 이후 다른 값을 재할당 할 수는 있다.

 

3. const -  중복 선언 불가능 / 재할당 불가능

const name = 'first';
console.log(name); // first

const name = 'second';
console.log(name);
// Uncaught SyntaxError: Identifier 'name' has already been declared

name = 'third';
console.log(name);
// Uncaught TypeError: Assignment to constant variable

 

const는 해당 변수가 이미 선언되었다는 에러 메시지가 출력되며, 중복 선언이 불가능하다.
var과 let와 다르게 name = 'third' 와 같이 변수 선언 및 초기화 이후에 다른 값을 재할당 할 수는 없다.

function func() {
	const list = ["A", "B", "C"]

    list = "D";
    console.log(list);
    // TypeError: Assignment to constant variable

    list.push("D");
    console.log(list); // ["A", "B", "C", "D"]
}

그러나 '값의 재할당'만 불가능할 뿐, 위의 예제처럼 배열과 오브젝트의 값을 변경하는것은 가능하다.

const name = 1;

const name2;  // SyntaxError: Missing initializer in const declaration

추가로 const는 선언할 때 반드시 초기화(값 할당)를 해주어야 한다.

 

# 스코프

스코프란 유효한 참조범위를 의미한다.

1. var -  함수 레벨 스코프(function-level scope)

function hello(){
    var a = 10;
    console.log(a);
}

hello(); // 10

console.log(a);  //ReferenceError: a is not defined

---------------------------------------------------------------------------

if(true) {
    var a = 10;
    console.log(a); // 10
}


console.log(a);  // 10

var은 함수 내에서 선언된 변수는 함수 안에서만 유효하며 외부에서는 참조가 불가능하다.(지역변수)

하지만 함수 외부에서 선언한 변수의 겨우에는 '전역변수'로 취급한다.

2. let, const -  블록 레벨 스코프(block-level scope)

if(true) {
    let a = 10;
    console.log(a); // 10
}

console.log(a);  // ReferenceError: a is not defined

---------------------------------------------------------------------------

function hello() {
    let a = 10;
    console.log(a); // 10
}

console.log(a);  // ReferenceError: a is not defined

let와 const는 함수, if문, for문, while문, try/catch문 등의 모든 코드 블록 ({...}) 내부에서 선언된 변수는 코드 블록 내에서만 유효하며 코드 블록 외부에서는 참조할 수 없다. 즉, 코드 블록 내부에서 선언한 변수는 지역 변수로 취급된다.

# 호이스팅

호이스팅이란 함수 내부에 있는 선언들을 끌어올려서 함수 유효범위의 최상단에 선언하는 것을 의미한다. 물리적으로 끌어올리는 것이 아니다. JavaScript의 Parser가 함수 실행 전 해당 함수를 한 번 훑는 과정에서 내부적으로 끌어올려 처리한다.

 

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

console.log(bar); // Error: Uncaught ReferenceError: bar is not defined
let bar;

var과 let,const(둘의 처리 방식 동일)를 살펴보면,  var 로 선언된 변수와는 달리 let 로 선언된 변수를 선언문 이전에 참조하면 참조 에러(ReferenceError)가 발생한다.

 

이는 let 로 선언된 변수는 스코프의 시작에서 변수의 선언까지 일시적 사각지대(Temporal Dead Zone; TDZ)에 빠지기 때문이다.

 

변수는 선언단계  > 초기화 단계 > 할당 단계에 걸쳐 생성되는데

 

var 으로 선언된 변수는 선언 단계와 초기화 단계가 한번에 이루어진다. 하지만, let 으로 선언된 변수는 선언 단계와 초기화 단계가 분리되어 진행된다.

// var
// 스코프의 선두에서 선언 단계와 초기화 단계가 실행된다.
// 따라서 변수 선언문 이전에 변수를 참조할 수 있다.

console.log(foo); // undefined

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

foo = 1; // 할당문에서 할당 단계가 실행된다.
console.log(foo); // 1

---------------------------------------------------------------------------
// let
// 스코프의 선두에서 선언 단계가 실행된다.
// 아직 변수가 초기화(메모리 공간 확보와 undefined로 초기화)되지 않았다.
// 따라서 변수 선언문 이전에 변수를 참조할 수 없다.

console.log(foo); // ReferenceError: foo is not defined

let foo; // 변수 선언문에서 초기화 단계가 실행된다.
console.log(foo); // undefined

foo = 1; // 할당문에서 할당 단계가 실행된다.
console.log(foo); // 1

 

# 재할당이 많은 특수한 경우 let를 사용하며, 기본적으로는  const를 사용한다.

<참조>

1. https://velog.io/@bathingape/JavaScript-var-let-const-%EC%B0%A8%EC%9D%B4%EC%A0%90

2. https://80000coding.oopy.io/e1721710-536f-43f2-823b-663389f5fbfa

3. https://curryyou.tistory.com/192

728x90
반응형