불변객체란 객체 내부의 프로퍼티들을 변경할 수 없도록 되어있는 객체, 값으로 전달받은 객체에 변경을 가하더라도 원본 객체는 변하지 않아야 하는 경우에 불변객체가 필요하다.
let person = {
name : "tom",
gender : "male",
age: 15
}
const changeName = function (person, newName) {
let newUser = person;
newUser.name = newName;
return newUser;
};
let person2 = changeName(person, "holland");
let person3 = changeName(person2, "hardy");
console.log(person.name); //hardy
console.log(person2.name); //hardy
console.log(person3.name); //hardy
📌 문제점!
같은 객체를 가리키는 새로운 변수만을 생성하고 그 변수가 가리키는 name 프로퍼티의 값을 변경해주었다.
person~person3까지 모든 변수는 같은 주소를 바라보고 있고 그 주소공간 중 name 프로퍼티가 가리키는
데이터를 변경해서 모든 변수에 담긴 name 프로퍼티 값이 다같이 변경되는 현상이 발생한다.
📌 불변 객체가 필요한 이유
이렇게 객체를 생성하면 원하지 않는 객체의 값마저 변경된다. 따라서 불변 객체가 필요하다.
원본 객체 내부의 프로퍼티들을 복사한 새로운 객체를 생성하여 변수에 할당해줘야 한다.
변수를 선언하고, 매개변수로 전달된 person 변수를 할당하는 것이 아닌, 새로운 객체를 생성해서 person의 내부 프로퍼티들을 담아준다.
let person = {
name : "tom",
gender : "male",
age: 15
}
const changeName = function (person, newName) {
return {
name : newName,
gender : person.gender,
age : person.age
}
};
person2 = changeName(person, "holland");
person3 = changeName(person2, "hardy");
console.log(person.name); //tom
console.log(person2.name); //holland
console.log(person3.name); //hardy
const copyObj = function (target) {
const newObject = {}; // newObject 빈 객체 생성
// for in 반복문으로 새 객체에 원래 객체의 프로퍼티들을 복사하는 함수
// target의 각 프로퍼티값을 가져올 수 있다.
for( let prop in target) {
newObject[prop] = target[prop];
}
return newObject;
};
let person = {
name : "tom",
gender : "male",
age: 15
}
let person2 = copyObj(people);
person2.name = "holland";
console.log(person);
console.log(person2);
👉 chageName()과 차이점?
👉 얕은 복사 만으로는 중첩된 객체를 제대로 복사할 수 없음
copyObject() 함수에서는 새로운 객체를 생성하여 새로운 객체에 target객체의 프로퍼티들을 할당하고 있다.
하지만 target 객체 내부의 프로퍼티가 또다른 객체를 가리키는 참조변수라면 user와 user2에 담긴 friends 프로퍼티에는 같은 객체를 가리키는 주소값이 담기게 된다.
얕은 복사는 한 객체가 가지는 바로 하위의 프로퍼티들만을 복사하는 것이다. 이런 이유로 user객체가 가지고 있는 또 다른 객체인 friends 배열에 대해 복사가 이루어지지 않아서 user와 user2가 같은 friends 배열을 바라보게 된다.
let user = {
name : "tommy",
friends : [
"a", "b", "c"
]
}
user2 = copyObject(user.friends);
user2.friends[0] = "D";
console.log(user.friends); // ["D", "B", "C"]
console.log(user2.friends); // ["D", "B", "C"]
얕은 복사를 통해 한단계만 복사를 해서 내부에 또 객체가 있는 경우에 발생하는 문제를 해결하기 위함, 재귀 함수를 사용하는 것이 가장 좋음
const deepCopyObject = function (target) {
let newObject = {}; // newObject 빈 객체 생성
if (typeof target === "object" && target !== null) {
for (let prop in target) {
console.log(newObject[prop] = deepCopyObject(target[prop]));
}
} else {
newObject = target;
}
return newObject;
};
let user = {
name : "tommy",
friends : [
"a", "b", "c"
]
}
user2 = deepCopyObject(user);
user2.friends[0] = "d"
console.log(user.friends);
console.log(user2.friends);
const obj = {a:1};
const newObj = Object.assign({}, obj);
newObj.a = 2;
console.log(obj) // { a: 1 }
console.log(newObj) // { a: 2 }
console.log(obj === newObj) // false
const obj = {
a: 1,
b: {
c: 2,
},
};
const newObj = Object.assign({}, obj);
newObj.b.c = 3;
console.log(obj); // { a: 1, b: { c: 3 } }
console.log(newObj) // { a: 1, b: { c: 3 } }
console.log(obj.b.c === newObj.b.c); // true
const obj = {
a: 1,
b: {
c: 2,
},
};
const newObj = { ...obj };
newObj.b.c = 3;
console.log(obj); // { a: 1, b: { c: 3 } }
console.log(obj.b.c === newObj.b.c); // true
const obj = {
a: 1,
b: {
c: 2,
},
};
const newObj = JSON.parse(JSON.stringify(obj));
newObj.b.c = 3;
console.log(obj); // { a: 1, b: { c: 2 } }
console.log(obj.b.c === newObj.b.c); // false
const obj = {
a: 1,
b: {
c: 2,
},
func: function() {
return this.a;
}
};
const newObj = JSON.parse(JSON.stringify(obj));
console.log(newObj.func); // undefined
https://galid1.tistory.com/663
https://hanamon.kr/javascript-shallow-copy-deep-copy/
https://helloinyong.tistory.com/267
https://velog.io/@jujusnake/JavaScript-불변-객체-immutable-objec