Javascript mutation assignment

2024년 02월 02일

object, array의 const

const dugi = {
	city: "Seoul",
	age: 30
}

dugi.city = "Sydney";
console.log(dugi.city) //"Sydney"
dugi.hobby = "Running"
console.log(dugi) //{city: 'Sydney', age: 30, hobby: 'Running'}

위 코드에서 const로 object를 만들었다. 하지만 내부의 프로퍼티의 값을 변경할 수 있다. hobby라는 프로퍼티를 추가하는 것도 가능하다.

const fruits = ["banana", "apple"];
fruits.pop()
fruits.pop()

console.log(fruits); // []
fruits.push("melon"); 

const로 만든 array가 있다. const로 만들었지만 array 역시 element를 추가하거나 삭제하는 것이 가능하다.

왜 그럴까? 이해하기 위해서 mutation과 assignment 개념을 알아야한다.

mutation vs assignment

assignment

처음 코딩을 배울 때 변수를 만드는 걸 이렇게 이해했다. 변수라는 빈 공간을 만들고 거기안에 데이터를 넣는거라고. 그리고 let 으로 만든 변수는 안에 내용물을 바꿀 수 있고 const 는 바꿀 수 없는 거라고. 코드를 쓰는 형태 자체도 이렇게 생각하게 만든다. const name = "dugi"; 이런식이니까

근데 사실 이건 틀린 멘탈 모델이고, 실제로는 이렇게 된다. object(array도 object 데이터 타입이므로 마찬가지)가 별도로 만들어지고 변수 dugi와 연결(assign)된다.

const는 이 연결은 바꿀 수 없고, let은 바꿀 수 있다. assign을 변경할 수 없으면 const 바꿀 수 있으면 let이다.

mutation

반대로 위의 예시에서 처럼 const 여도 { } 안의 내용은 변경이 가능하다. 마찬가지로 [ ]안의 내용도 변경이 가능하다. 왜 그럴까.

dugi 와 연결된 { } 는 다른 { } 로 연결이 바뀌지 않았고, { } 의 key,value만 바뀌었기 때문이다. { } 안의 내용을 변경하는 것을 mutation이라고 한다. key:value쌍을 추가할수도 있고, 특정 key의 value만 바꿀 수도 있다. array라면 요소를 추가하거나 삭제할 수 있다.

const dugi = {
	city: "Seoul",
	age: 30
};

dugi.city = "Jeju"; //mutation
dugi.age = 40; //mutation

하지만 아래와 같은 변경은 불가능하다. 기존에 있던 { } 의 내용을 바꾸는 게 아니라, 아예 새로운 { } 를 만들어 할당(assgin)하려는 코드이기 때문이다.

dugi = {
	city: "Jeju",
	age: 40
} 
//Uncaught TypeError: Assignment to constant variable.

object안의 object

그럼 이건 어떨까.

const dugi = {
	address : {
		city: "Seoul"
	},
	age: 30
};

const summer = {
	address : dugi.address,
	age: 31
}

summer.address.city = "Jeju"
console.log(dugi.address); //{city: "Jeju"}

summeraddress.city 를 바꿨는데 왜 dugiaddress.city 가 바뀌었을까?

자바스크립트의 객체 ( { }로 감싸진 단위) 하나하나는 별도로 존재한다.

summer의 address를 dugi.address로 할당했기 때문에 summer.address는 dugi.address와 같은 {city: "Seoul"} 객체에 연결되어 있다. 그렇기 때문에 어디서든 그 객체의 key value를 변경(mutation)하면 summer.address dugi.address 모두에서 변경이 된다.

얕은 복사

객체를 아래처럼 만들면 최초 깊이의 프로퍼티는 값만 가져와서 공유가 되지만 그 이상 깊이의 내부 객체는 원본을 공유한다. 그렇기에 변경시 원본에 영향을 끼친다.

const dugi = {
	address : {
		city: "Seoul"
	},
	age: 30
};

const summer = { ...dugi };

summer.age = 40;
summer.address.city = "Jeju";

console.log(dugi);
//{ address: {city: "Jeju", age: 30};

깊은 복사

복사한 객체에서 변경을 했는데, 원래의 객체는 변경을 원하지 않을 경우가 있다. 그럴때는 이런 방법이 있다.

1 Object.freeze 메서드 사용

const summer = {};
summer.address = Object.freeze(dugi.address);

summer.address.city = "Jeju";
console.log(dugi.address.city); //Seoul

2 JSON.parse(JSON.stringify()) 사용

const summer = {};
summer.address = JSON.parse(JSON.stringify(dugi.address));

summer.address.city = "Jeju";
console.log(dugi.address.city); //Seoul

정리

  • let const 는 assign을 변경할 수 있는지 없는지에 영향을 끼친다. const는 assign 변경이 불가하다.
  • const 라도 연결된 객체를 유지한테 객체 내부의 값을 변경, 추가, 삭제할 수 있다.
  • 객체는 { } 마다 별도의 객체가 생성되는 것이라서 객체를 복사할 때 객체 내부의 객체는 실제로는 복사되는 것이 아니라 원본에 연결(assign)된다.

TAGS
JAVASCRIPT