변경 불가능한 값(immutable)임을 의미한다. (ex. number, string, boolean, undefined, null, symbol)
변경 불가능하다는 의미가 무엇인지 알아보자.
let str = "deer";
str[2] = "a";
console.log(str) = "deer";
일부 문자열 변경을 시도해도 str은 변하지 않는다. (에러도 나지 않는다.)
let score;
score = 80;
score = 90;
이때 변수에 다른 값을 재할당하려면 (변수가 참조하던 메모리 공간 내의 값 80을 지우고 90으로 변경하는 것이 아니라) 변수가 가리키던 메모리 공간의 주소를 다른 곳으로 바꿔줘야 한다.
더 이상 참조하지 않는 기존의 원시값(그림에서는 undefined와 80)은 어떻게 될까? 가비지 콜렉터가 예상치 못한 시점에 청소해준다!
변경 가능한 값(mutable)임을 의미한다.
변경 가능하다는 의미가 무엇인지 알아보자.
const person = {
name : "Jasmine"
}
console.log(person) // { name : "Jasmine" }
person.name = "자스민"
console.log(person) // { name : "자스민" }
참조 자료형이 변경 가능한 값이기 때문에 생기는 장점과 단점이 있다.
객체 프로퍼티 변경 시, 원시값마냥 객체 자체를 복사하지 않아도 되기 때문에
메모리 사용 효율성과 성능 향상 측면에서 이점이 있다.
여러개의 식별자(변수)가 하나의 객체를 공유하게 되는 경우,
객체 원본과 사본 중 어느 한쪽의 프로퍼티 값을 변경하면 다른 한쪽도 변한다.
따라서 원본 객체를 유지한 상태로 값을 변경한 객체를 사용하고 싶다면 복사해야 한다. 이제 얕은 복사와 깊은 복사의 차이에 대해 알아보자.
얕은 복사(shallow copy)와 깊은 복사(deep copy)는 맥락에 따라서 의미가 달라진다. (두통 유발 원인이었지만 유어클래스를 잘 읽어보고 해소되었다!)
원시 값을 할당한 변수를 다른 변수에 할당하는 것
원시값 1이 할당된 변수 a를 b에 할당하는 것을 깊은 복사라고 할 때가 있다.
const a = 1;
const b = a;
console.log(a === b) // true (깊은 복사) => 값 자체를 복사
객체를 할당한 변수를 다른 변수에 할당하는 것을 얕은 복사라고 할 때가 있다.
const obj = {x : 1};
const copiedObj = obj;
console.log(obj === copiedObj) (얕은 복사) => 메모리 주소만 복사
헷갈리니까 맥락1을 잠시 머릿속에서 비워내고 맥락2를 보자.
2개 이상의 참조자료형(객체, 배열 등)이 중첩되었다고 가정하고 설명하는 맥락이다.
내부에 중첩된 참조자료형(이하 '중첩된 객체'로 표현하겠음)이 있는 참조자료형 arr와 obj가 있다고 하자.
let arr = [1, 2, [3, 4], 5];
let obj = [{ coffee1 : "MegaCoffee"},{coffee2 : "Starbucks"}];
중첩된 객체를 가진 객체를 복사하면 한 단계의 복사본만 만듦.
// slice()로 복사
const copiedArr1 = arr.slice();
console.log(arr === copiedArr1) // false
console.log(arr[2] === copiedArr1[2]) // true
// spread 연산자로 복사
const copiedArr2 = [...arr];
console.log(arr === copiedArr2) // false
console.log(arr[2] === copiedArr2[2] // true
arr의 복사본이 만들어졌지만(1단계만 복사), 중첩된 객체(배열)인 arr[2] = [3, 4]는 복사본이 만들어지지 않았다. arr[2], copiedArr1[2], copiedArr2[2]는 복사된 적이 없어 유일한 중첩된 객체를 가리키고 있다.
const copiedObj1 = Object.assign({},obj);
const copiedObj2 = {...obj};
console.log(obj === copiedObj1) // false
console.log(obj === copiedObj2) // false
console.log(obj[1] === copiedObj1[1]) // true
console.log(obj[1] === copiedObj2[1] // true
obj의 복사본이 만들어졌지만(1단계만 복사), 중첩된 객체인 { coffee1 : "MegaCoffee"}와 {coffee2 : "Starbucks"}는 복사본이 만들어지지 않았다. arr[1], copiedObj1[1], copiedObj2[1]는 복사된 적 없어 유일한 중첩된 객체를 가리키고 있다.
객체가 중첩되어 있을 때 중첩된 객체의 복사본까지 전부 만듦.
const copiedArr_JSON = JSON.parse(JSON.stringify(arr));
console.log(arr === copiedArr_JSON); // false
console.log(arr[2] === copiedArr1[2]); // false
❗️ 단 이 방법을 함수가 중첩되어 있는 객체에 사용하면 함수는 복사되지 않고 null로 바뀐다.
const copiedArrContainsFn_JSON = JSON.parse(JSON.stringify(["1", function(){}]))
console.log(copiedArrContainsFn_JSON) // ["1", null]
npm install lodash
깊복을 원한다면 lodash를 설치하자!! (node.js 환경에서 실행)
const copiedArr_JSON = JSON.parse(JSON.stringify(arr));
console.log(arr === copiedArr_JSON); // false
console.log(arr[2] === copiedArr1[2]); // false
중첩된 객체인 arr[2]까지 모두 복사되었다.
틀린 부분이 있다면 지적 감사하겠습니다 ~~!!