값으로 전달받은 객체에 변경을 가하더라도 원복 객체는 변하지 않아야 하는 경우
불변 객체를 사용한다.
객체의 가변성에 따른 문제점
var user = {
name: 'Jaenam',
gender: 'male'
};
var chaneName = function (user, newName) {
var newUser = user;
newUser.name = newName;
return newName;
};
var user2 = changeName(user, 'Jung');
if (user !== user2) {
console.log('유저 정보가 변경되었습니다.');
}
console.log(user.name, user2.name); //Jung Jung
console.log(user === user2) // true
user 객체를 생성하고 user 객체의 name 프로퍼티를 'Jung'으로 바꾸는 changeName을 호출해 그 결과를 user2에 담았다.
이후 user 변수와 user2 변수가 서로 같지 않다는 조건이 성립하면 '유저 정보가 변경되었습니다.'가 출력되겠지만 실제로는 출력 없이 통과하고,
두 변수의 name 프로퍼티 모두 'Jung'으로 출력된다.
만약 정보가 바뀐 시점에 알림을 보내야 한다거나, 바뀌지 전의 정보와 후의 정보의 차이를 보여주려면 아래와 같이 변경해야한다.
var user = {
name: 'Jaenam',
gender: 'male'
};
var chngeName = function (user, newName) {
return {
name: newName,
gender: user.gender;
};
};
var user2 = changeName(user, 'Jung');
if (user !== user2) {
console.log('유저 정보가 변경되었습니다.');
}
console.log(user.name, user2.name); //Jaenam Jung
console.log(user === user2) // false
changeName 함수가 새로운 객체를 반환하도록 수정했다.
이 경우 user와 user2는 서로 다른 객체이므로 변경 전 후를 비교할 수 있다.
하지만 changeName 함수는 새로운 객체를 만들면서 변경할 필요 없는 기존 객체의 프로퍼티(gender)를 하드코딩으로 입력했다.
이런 식으로는 대상 객체에 정보가 많을수록, 변경해야 하는 정보가 많아진다.
이 경우 대상 객체의 프로퍼티 개수에 상관없이 모든 프로퍼티를 복사하는 함수를 만드는 편이 더욱 좋다.
var copyObject = function (target) {
var result = {};
for (var prop in target) {
result[prop] = target[prop];
}
return result;
};
copyObject는 for in 문법을 이용해 result 객체에 target 객체의 프로퍼티들을 복사하는 함수이다.
var user = {
name: 'Jaenam',
gender: 'male'
};
var user2 = copyObject(user);
user2.name = 'Jung';
if (user !== user2) {
console.log('유저 정보가 변경되었습니다.');
}
console.log(user.name, user2.name); // Jaenam Jung
console.log(user === user2); // false
copyObject를 통해 간단하게 객체를 복사하고 내용을 수정했다.
하지만 위 경우 '얕은 복사만을 수행한다'라는 아쉬운 부분이 존재한다.