자바스크립트의 키워드 비교 var, let, const

Duboo·2023년 9월 26일
0
post-thumbnail

변수와 호이스팅
var, let, const에 대한 내용을 정리했지만 마음에 안들어서 다시 정리함


JS에서 변수 혹은 상수를 만들 때 사용하는 키워드를 비교

  • 변수를 선언할 때 사용 varlet
  • 상수를 선언할 때 사용 const

var / let

변수를 선언할 때 사용하는 키워드 var와 let을 비교

// var
var num = 10;
num = 20;

// let
let num = 10;
num = 20;

변수를 선언하고 할당하고 또 재할당을 해주면서 사용하는 두 키워드는 크게 차이가 없어 보이지만 몇가지 다른 부분이 있는데 이 다른 부분이 매우 중요합니다.


var / let - 스코프 (Scope)

스코프는 범위로 이는 변수가 살아있는 범위라고 생각할 수 있습니다.
다른 말로 코드가 변수에 접근할 수 있는 범위를 뜻합니다.

스코프의 종류

  • Function Scope - 함수 범위
  • Block Scope - 블록 범위
  • Global Scope - 전역 범위

가장 먼저 살펴볼 차이는 스코프로 var는 함수 let은 블록 범위의 스코프를 가집니다.

const main = () => {
    var x = 'var hi'
    let y = 'let hi'
}

console.log(x);
console.log(y);

위 코드 콘솔의 결과는 ReferenceError가 나옵니다.

당연히 함수 내부에서 선언한 변수들은 함수 외부에서 불러올 수 없기 때문인데

const main = () => {
    var x = 'var hi'
    let y = 'let hi'
    
    console.log(x);
	console.log(y);
}

main();
// var hi
// let hi

로그를 함수 내부에서 찍어보면 원하는 결과를 얻을 수 있습니다.

여기까지는 두 키워드가 같아 보이니, 코드를 추가해봅니다.

const main = () => {
  	if(true) {
	    var x = 'var hi'
    	let y = 'let hi'
        
        console.log(x);
		console.log(y);
    }
}

main();
// var hi
// let hi

조건문안에 선언한 변수들을 조건문 안에서 불러오고 있습니다.
두 콘솔 모두 정상적으로 출력됩니다.

const main = () => {
  	if(true) {
	    var x = 'var hi'
    	let y = 'let hi'
    }
        console.log(x);
		console.log(y);
}

main();
// var hi
// ReferenceError: y is not defined

이번엔 조건문안에 선언한 변수들을 조건문 밖에서 불러오고 있습니다.

위 함수실행 결과는 조건문 외부에 있는 콘솔에서 조건문 안에 var 키워드로 선언한 x 변수의 값은 가져올 수 있지만 let 키워드로 선언한 y 변수의 값은 가져올 수 없기 때문에 ReferenceError: y is not defined가 나오는걸 확인할 수 있습니다.

앞서 언급한 "var는 함수 let은 블록 범위의 스코프를 가진다"를 위 코드에서 확인할 수 있습니다.


// let
for(let i=1; i<3; i++) {
  console.log(i);
}
console.log(i);
// 1
// 2
// ReferenceError: i is not defined


// var
for(var i=1; i<3; i++) {
  console.log(i);
}
console.log(i);
// 1
// 2
// 3

이러한 var는 일반적인 프로그래밍 언어와 다르게 동작합니다.
"블록안에 선언한 변수를 블록 밖에서 접근할 수 있다?"

var 키워드로 선언한 변수가 자동으로 함수 레벨의 스코프를 가지기 때문에 가능한 것인데,
이는 변수가 선언된 함수 내부라면 어디서든지 변수에 접근할 수 있다는 말입니다.

반면 let 키워드로 선언한 변수는 블록 레벨의 스코프를 가지기 때문에 블록의 밖에서는 변수에 접근할 수 없습니다.


const main = () => {
	var x = "hi";
  	if(true) {
    	var x = "bye";
    }
	console.log(x);
}

main(); // bye

또한 var 키워드는 같은 소코프안에서 변수의 중복 선언을 허용하기 때문에 조건문 블록안에 동일한 변수명으로 선언한 값으로 외부 변수의 값이 덮어씌워지는걸 확인할 수 있습니다.

Global

var globalVar = "globalVar"; 
let globalLet = "globalLet";

위처럼 함수 외부에 전역적으로 선언된 변수들은 전역 변수에 해당하는데, 이러한 전역 변수에서도 차이가 존재합니다.

var 키워드로 전역에 선언한 변수는 브라우저 최상위에 존재하는 window 객체의 속성으로 등록되지만 let 키워드로 선언한 변수는 그렇지 않습니다.

이것이 문제가 되는 이유는 window 객체는 브라우저의 모든 정보를 가지고 있는 최상위 전역 객체로 개발자가 작성한 코드, 라이브러리등을 전역에서 공유하기 때문인데,

이는 어디서든 전역으로 선언한 var 변수에 접근이 가능하다는 말이고 의도치 않게 값이 변경될 수 있기 때문입니다.


var / let - 중복 선언 (Variable redeclaration)

// var
var x = "curVal";

var x = "changeVal";

console.log(x); // changeVal

// let
let y = "curVal";

let y = "changeVal"; // Identifier 'y' has already been declared

var와 let 키워드의 또 다른 차이는 중복 선언을 허용하는가 아닌가에 대한 차이입니다.

  • var 중복 선언 가능
  • let 중복 선언 불가능

중복 선언이 가능하다면 협업에서 매우 치명적으로 작용할 수 있는데 내가 선언한 변수와 다른 사람이 선언한 변수명이 같다면 의도치 않게 값이 변질될 수 있기 때문입니다.


var / let -호이스팅 (Hoisting)

console.log(num); // undefined
var num = 10;
console.log(num); // 10

호이스팅

프로그램이 실행되기 이전에 변수의 선언과 초기화를 분리해서 변수의 선언 부분만 프로그램 최상단으로 끌어올리는걸 말합니다.

다른 말로 프로그램이 실행되기 이전에 JS에게 우리가 사용하려는 변수들을 미리 알려주는 것과 같습니다.

Javascript에서 호이스팅은 인터프리터가 변수와 함수의 메모리 공간을 선언 전에 미리 할당하는 것을 말합니다.

var num // 변수의 선언
console.log(num); // undefined
num = 10; // 초기화

console.log(num); // 10

코드 상으로는 변수의 선언과 초기화가 동시에 (var num = 10) 이루어 졌지만 호이스팅 과정에서 변수의 선언문이 프로그램 최상단으로 올가가게 됩니다.

코드로 풀어보자면 위 코드와 같은 모습이며, 따라서 출력으로 undefined가 나오는 것입니다.



그래서 var 키워드로 선언된 변수는 호이스팅이 되서 최상단으로 끌어올려지며 자동으로 undefined로 초기화가 진행된다는 특징을 확인할 수 있습니다.

let 비교

console.log(num); // Uncaught ReferenceError: Cannot access 'num' before initialization
let num = 10;

반면 let 키워드로 선언한 변수의 경우 Cannot access 'num' before initialization 에러로 num을 초기화 하기전에는 접근할 수 없다는 참조 에러가 출력됩니다.

그렇다고 let 키워드로 선언한 변수는 최상단으로 호이스팅하지 않는가?는 아닙니다.
let으로 선언한 변수도 최상단으로 호이스팅이 되지만 var와는 달리 초기화하지 않습니다.

조금더 정확히는 초기화를 할 수 없습니다.


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

"호이스팅이 되지만 왜 선언문 이전에 접근할 수 없는가??"

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

let으로 선언된 변수는 호이스팅이 되어서 최상단으로 끌어올려지긴 하지만 초기화를 할 수 없는데,

그 이유는 코드상에 존재하는 선언문에 닿기까지는 일시적 사각지대에 들어가게됩니다.

다시말해 최상단으로 끌어올려진 let 변수는 일시적 사각지대 안에 들어가져 있는 상태입니다.

JS는 일시적 사각지대안에 들어가있는 변수에 접근을 허용하지 않습니다.
따라서 접근조차 불가능하며 당연히 undefined로 초기화 조차 불가능합니다.


const

const 키워드는 let 키워드와 공통된 부분이 많습니다.

  • Block Scope
  • 중복 선언 불가
  • 선언문 이전에 접근 불가

한가지 다른 점은 변수를 선언하는 let과 달리 변하지 않는 상수를 선언할 때 사용하는 키워드라는 점입니다.

const age = 10;
age = 20; // X Uncaught TypeError: Assignment to constant variable

또한 const의 경우 선언만 하는 코드도 작성할 수 없습니다.

let num;const num;

이는 어찌보면 당연한데 재할당이 가능한 let의 경우 언제든지 값을 할당해줄 수 있지만

const는 재할당이 불가능하기 때문입니다.

let num;
num = 10;const num;
num = 10; // 불가능

주의할 점은 재할당은 불가능하다는 의미가 값을 변경할 수 없다는 의미는 아닙니다.

이는 js의 2가지 데이터 타입인 원시 타입과 참조 타입에 대해 알고 있어야합니다.

js의 데이터 타입에 관련된 내용 👈

profile
둡둡

0개의 댓글