본 게시글은 개인 공부를 하면서 기록 목적으로 작성하였습니다.
잘못된 내용이 있다면 제보 부탁드립니다. 감사합니다.🙇♂️
1. 개 요
JavaScript를 공부하다가 const로 선언한 변수의 값은 재할당을 할 수 없는데, 그 동안 프로젝트를 만들었던 코드를 보면
"const 키워드로 변수에 객체를 할당한 경우 왜 재할당이 되는 거지?" 라는 것에 의문이 생겨 자료를 찾아보게 되었다.
먼저, 이 글을 통해 JavaScript 변수 선언 방법 기초적인 내용부터 하나씩 기록을 남겨 보고자 한다.
2. 변수 선언
- JavaScript는 느슨한 타입을 가진 언어이기 때문에 데이터 타입을 따로 명시하지 않고 변수를 선언할 수 있다.
- 변수를 선언할 때 타입을 명시하지 않는 것일 뿐, 느슨한 타입이라고 해서 타입이 존재하지 않는 것이 아니라,
내부적으로는 데이터의 종류에 따른 변수의 타입을 가진다. - JavaScript 에서는 var, let, const 를 통해 변수를 선언할 수 있다.
var
- var는 ES6(ES2015)에서 let과 const가 등장하기 전까지 변수를 선언할 수 있는 유일한 방법이었다.
- var로 선언된 변수는 기존에 선언된 변수의 값을 덮어쓰며, 함수 스코프를 기준으로 동작한다.
- 스코프란?
- 스코프는 어떤 변수들에 접근할 수 있는지 정의한 범위를 말한다.
- 함수 스코프를 기준으로 동작한다는 것은?
- 변수를 선언한 함수 몸체 안에서만 해당 변수에 접근할 수 있다는 의미를 말한다.
- 변수를 선언한 함수 몸체 안에서만 해당 변수에 접근할 수 있다는 의미를 말한다.
- var로 선언한 변수는 스코프 내에 이미 동일한 식별자를 가진 변수가 존재한다면 해당 변수에 값을 재할당한다.
{
var a = 1;
}
console.log(a); // 1
var a = 2;
console.log(a); // 2
let 과 const
- let 과 const는 ES6(ES2015)에서 등장한 변수 선언 키워드로 var와 달리 재선언을 허용하지 않는다.
- let 과 const는 블록 스코프를 가지고 있어 변수를 둘러싼 블록({})에서만 해당 변수에 접근할 수 있다.
- let은 값을 재할당 하는 것이 가능하지만, const는 값을 재할당 하는 것이 불가하다.
// 블록 레벨
{
let a = 1;
console.log(a); // 1
}
console.log(a); // Uncaught ReferenceError: a is not defined
// 재선언
{
let b = 1;
let b = 2; // Uncaught SyntaxError: Identifier 'b' has already been declared
}
// 재할당
}
let c = 1;
c = 2;
console.log(c); // 2
}
3. 원시 값과 객체
원시 타입 (Primitive Type)
- JavaScript에서 원시 타입은 7가지가 존재한다.
- number
- string
- boolean
- null
- undefined
- Symbol
- BigInt (ES2020에서 추가)
- 원시 타입의 값은 읽기 전용으로 변경할 수 없으며, 변수에 할당하면 그 변수에는 실제 값이 저장된다.
객체 (참조형)
- JavaScript에서 원시 타입이 아닌 모든 값은 객체이다.
- 객체는 key: value 형태로 여러 값을 포함하는 컨테이너이며, 내부의 값은 얼마든지 변경할 수 있다.
- 객체를 변수에 할당하면 변수에는 참조 값이 저장된다.
4. var, let 값의 재할당
- var, let 키워드로 선언한 변수는 값을 재할당 할 수 있다.
- 재할당이란, 현재 변수에 저장된 값을 버리고 새로운 값을 저장할 수 있는 것을 말한다.
- 아래 예제와 같이 변수에 값을 재할당하면 이전 값 20이 저장되어 있던 메모리 공간을 지우고 그 메모리 공간에
재할당 값 30을 저장하는 것이 아니라, 새로운 메모리 공간을 확보하고 그 메모리 공간에 숫자 값 30을 저장한다. - age 변수의 값이 30으로 재할당 되면서 이전 값인 20은 어떤 식별자와도 연결되어 있지 않기에 이러한 불필요한 값들은
가비지 콜렉터에 의해 메모리에서 자동 해제된다. (※ 단, 메모리에서 언제 해제될지는 예측할 수 없다.)
let age = 20;
console.log(age); // 20
age = 30;
console.log(age); // 30
가비지 콜렉터란?
- 어플리케이션이 할당한 메모리 공간을 주기적으로 검사하여 어떤 식별자도 참조하지 않은 메모리를 해제하는 기능을 말한다.
- JavaScript는 가비지 콜렉터를 내장하고 있는 매니지드 언어로서 더 이상 사용되지 않는 메모리를 해제하여 메모리 누수를 방지한다.
5. const 값의 재할당
- const 키워드로 선언된 변수에 원시 값을 할당한 경우 원시 값은 불변성을 갖기에 변경할 수 없다.
const fruit = "apple";
fruit = "peach"; // Uncaught TypeError: Assignment to constant variable.
- 하지만, const 키워드로 선언된 변수에 객체를 할당한 경우 메모리에 저장되어 있는 참조 값을 통해 실제 객체에 접근한다.
- 객체는 변경이 가능한 값으로 객체를 할당한 변수는 재할당 없이 동적으로 프로퍼티의 값을 추가하고 삭제할 수 있다.
const user = {name: "kyoo"};
console.log(user); // {name: "kyoo"};
user.name = "dromy";
console.log(user); // {name: "dromy"};
6. 결 론
const 키워드로 선언된 변수에 원시 값을 할당할 경우 불변성을 갖기에 변경할 수 없다.
하지만, const 키워드로 객체를 할당할 경우 객체는 변경 가능한 값이므로 메모리에 저장된 객체를 직접 수정할 수 있다.
이 때 객체를 할당한 변수에 재할당을 하지 않았으므로 객체를 할당한 변수의 참조 값은 변경되지 않는다.
이에, 위 "1. 개요"에서 언급한 const 키워드로 변수에 객체를 할당한 경우 재할당이 가능한 것이었다.
지금까지 프로젝트에서 기능을 구현하는 것 위주로 공부만 하다보니 내가 작성하고 있는 코드가 맞는 것인지
이게 왜 이렇게 작동되는 것인지에 대한 원리도 모르는 채 코드를 작성하고 있었다는 것을 깨닫게 된 계기가 되었다.
이번 공부를 통해 JavaScript에 대해 조금 더 상세히 알 수 있었고, 궁금했던 의문이 풀렸지만,
추가적으로 Call By Value와 Call By Reference, 참조에 의한 객체 복사에 대해 궁금증이 생겼다.
공부를 할 수록 알아가는 것도 많고 알아야 할 것도 많지만 하나씩 차근차근 공부하며, 기록을 남기는 습관을 가져볼 것이다.
참 고
모던 자바스크립트 Deep Dive (이웅모)
기초부터 완성까지, 프런트엔드 (이재성, 한정)
Const 키워드를 사용 해도 값의 재할당이 일어날 수 있을까?
자바스크립트엔 여덟 가지 자료형(숫자형, bigint형, 문자형, 불린형, 객체형, Null형, Undefined형, 심볼형)이 있다. 이 중 일곱 개는 오직 하나의 데이터(문자열, 숫자 등)만 담을 수 있어 '원시형(primit
zeebeck.tistory.com