본문 바로가기
⚡️etc.

[JavaScript] var, let, const의 차이에 대해 알아보자(scope, hoisting...)

by s2ylvia 2024. 6. 19.

1. 중복 선언 가능 여부

  • var : 중복 선언이 가능하다.
var name = 'kim';
console.log(name); //kim

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

 

위와 같이 같은 이름으로 변수를 선언해도 에러없이 각각 다른 값이 출력된다.

이렇게 되면 나도 모르게 같은 이름의 변수를 만들어서 값이 재할당되는 치명적인 실수가 일어날 수 있다.

 

  • let/const : 중복 선언이 불가능하다.
let name = 'kim';
let name = 'lee'; //SyntaxError: Identifier 'menu' has already been declared

const name = 'kim';
const name = 'lee'; //SyntaxError: Identifier 'menu' has already been declared

 

let과 const는 한번 선언된 변수 이름으로 다시 변수를 만들 수 없다.

에러가 발생하므로, var와 달리 코드의 안정성을 높일 수 있다.

 

 

2. 재할당 가능 여부

  • var/let : 재할당이 가능하다.
//var
var name = 'kim';
console.log(name); //kim

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

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

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

 

var와 let은 변수 선언 및 초기화 이후로도 새로운 값으로 재할당이 가능하다.

 

  • const : 재할당이 불가능하다.
const name = "홍길동";
name = "이순신"; // TypeError: Assignment to constant variable.

 

const는 상수를 선언하는 키워드로, 변하지 않는 값이기 때문에 재할당을 할 수 없다.

const arr = [1, 2, 3];

// 배열의 요소를 변경하는 것은 가능
arr[0] = 4;
console.log(arr); // [4, 2, 3]

// 새로운 배열을 할당하려고 하면 에러 발생
// arr = [4, 5, 6]; // TypeError: Assignment to constant variable.

 

하지만 const가 변수 자체의 재할당을 막는 것이지, 변수의 내용(즉, 배열의 요소들)은 변경할 수 있도록 허용하기 때문에 배열이나 객체를 선언할 때 사용하면 된다.

 

3. 스코프 유효범위

스코프는 모든 식별자가 자신이 선언된 위치에 의해 다른 코드가 참조할 수 있는 유효 범위로, 즉 식별자가 유효한 범위이다.

 

  • var : 함수 레벨 스코프
function test(){
    var name = 'kim';
    console.log(name);
}

test(); //kim

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

 

var는 함수 내부에서 선언된 변수만 지역변수로 한정하고, 함수 내부가 아니면 모두 전역변수로 간주한다.

그래서 함수 내부에 있는 변수를 외부에서 참조하려고 하면 오류가 발생한다.

if(1){
    var name = 'kim';
    console.log(name); //kim
}

console.log(name); //kim

 

함수를 제외하면 if, for, while, try/catch 문 등의 코드 블록{}에서 var를 선언하면 모두 전역변수로 간주한다.

그래서 외부에서도 참조할 수 있다.

 

  • let/const : 블록 레벨 스코프

let과 const는 함수는 물론 if, for, while, try/catch 문 등의 코드 블록{}에서 사용된 모든 변수를 지역변수로 간주한다.

if(1){
    let name = 'kim';
    console.log(name); //kim
}

console.log(name); //ReferenceError: name is not defined
function test(){
    let name = 'kim';
    console.log(name);
}

test(); //kim

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

 

즉, var는 함수 내부에서 선언된 변수만 지역변수로 인정하는 함수 레벨 스코프이고(나머지는 다 전역변수로 취급),

let/const는 함수를 포함해서 코드 블록{} 내부에서 선언된 변수는 모두 지역변수로 인정하는 블록 레벨 스코프이다.

 

 

4. 호이스팅 방식

호이스팅은 자바스크립트 엔진이 코드를 실행하기 전에 변수 및 함수 선언을 메모리에 먼저 올리는 것이다.

 

호이스팅을 하는 이유는 선언을 스코프의 최상위로 올려서 어디서든 사용할 수 있게하여,

(뒤에서 선언된 변수를 앞의 코드에서 참조할 수 있다던가.....)

가독성을 높이고 유지보수성을 향상시키기 때문이다.

 

  • var
  console.log(num); // undefined

  var num = 10;

  console.log(num); // 10

 

var는 선언되기 전에 참조되었음에도 에러가 발생하지않고 undefined가 뜬다.

이는 코드를 실행하기 전에 미리 메모리에 올린 뒤 undefined로 초기화를 해두었기 때문이다.

 

  • let/const
console.log(coco); // ReferenceError: coco is not defined 
let coco = "코코";
console.log(coco); // 코코

console.log(coco); // ReferenceError: coco is not defined 
const coco = "코코";
console.log(coco); // 코코

 

let과 consts는 undefined가 아니라 에러가 발생한다.

이는 코드를 실행하기 전에 미리 메모리에 올리기는 하지만, 초기화는 코드 실행 과정에서 변수 선언문을 만났을 때 수행하기 때문이다.

 

그렇기 때문에 호이스팅이 발생하지만, 값을 참조할 수 없기 때문에 호이스팅이 발생하지 않는 것처럼 보이는 것이다.

 

 

결론

var는 이러한 특징 때문에 코드가 길어질수록 모든 코드를 읽어보게끔 하였고, 결과를 예측하기 힘들게 만들었다.

그래서 var의 사용은 지양해야한다.

우리는 const를 기본으로 사용하되, 재할당이 필요한 경우 let을 사용해 변수를 선언하면 된다.

 

 

 

 

 

 

 

참고

https://dev-coco.tistory.com/112