자바스크립트를 쓰는 개발자라면 매일 같이 마주하는
Object타입
이놈, 유용하지만 조심해서 써야한다.
코드를 쓰다보면 객체를 '복사'하게 되는 경우가 많은데 예를들면 아래와같다
const wallet = {
card: 3,
money: 0
};
const friend1_wallet = wallet;
const friend2_wallet = wallet;
console.log(wallet) // { card: 3, money: 0 }
console.log(friend1_wallet) // { card: 3, money: 0 }
console.log(friend2_wallet) // { card: 3, money: 0 }
자, 너무 나도 당연한 결과이다 그렇다면 이번엔 아래의 결과를 예상해보자
wallet.card = 4;
console.log(wallet);
console.log(friend1_wallet);
console.log(friend2_wallet);
아래의 결과가 정확히 예상되는가?
console.log(wallet); // { card: 4, money: 0 }
console.log(friend1_wallet); // { card: 4, money: 0 }
console.log(friend2_wallet); // { card: 4, money: 0 }
왜, 이런일이 생길까?
c와 같은 언어를 배우고 사용해본 개발자라면 메모리 참조에 대해서 알것이다.
const friend1_wallet = wallet; // 복사가 아닌 참조
friend1_wallet은 wallet이 가리키는 메모리 영역을 똑같이 바라보게 했을 뿐이기 때문에,
wallet을 바꾸면 당연하게도 firend1_wallet의 값이 바뀌게 되는것이다.
그렇다면,
"지갑을 똑같이 복사한 다음 복사한 지갑에만 카드를 두개 더 넣어두고싶어요~"
라고 했을때 어떻게 처리를 해야할까?
우리의 javacript는 이를 위해 Object.assign() 메소드를 제공한다.
const wallet = {
card: 3,
money: 0
};
const friend1_wallet = Object.assign({}, wallet);
const friend2_wallet = Object.assign({}, wallet);
console.log(wallet) // { card: 3, money: 0 }
console.log(friend1_wallet) // { card: 3, money: 0 }
console.log(friend2_wallet) // { card: 3, money: 0 }
이렇게 하면 우리는 빈 객체에 wallet을 복사하게 된다.
따라서, 아래와 같이 실했했을때 결과를 예상해보자.
wallet.card = 6;
console.log(wallet);
console.log(freind1_wallet)
console.log(freind2_wallet)
결과를 예상해봤는가?
console.log(wallet); // { card: 6, money: 0 }
console.log(freind1_wallet); // { card: 3, money: 0 }
console.log(freind2_wallet); // { card: 3, money: 0 }
자, 이제 목적을 달성했다.
그런데...
"저는 지갑에 어머니가 맡기신 돈도 보관해야되요. 돈을 두가지로 분류해서 저장해주세요!" 라고 한다면
const wallet = {
card: 3,
money: {
mother: 5000,
mine: 100,
},
};
const freind1_wallet = Object.assign({}, wallet);
const freind2_wallet = Object.assign({}, wallet);
console.log(wallet); // { card: 3, { mother: 5000, mine: 100 } }
console.log(freind1_wallet); // { card: 3, { mother: 5000, mine: 100 } }
console.log(freind2_wallet); // { card: 3, { mother: 5000, mine: 100 } }
자... 이런 상황에서 엄마가 1000원을 더 맡기셔서 wallet에 돈을 추가하는 상황이 되었다.
아래 상황의 결과를 예측해보자
wallet.money.mother += 3000;
console.log(wallet);
console.log(friend1_wallet);
console.log(friend2_wallet);
결과는 아래와 같다.
console.log(wallet); // { card: 3, money: { mother: 8000, mine: 100 } }
console.log(friend1_wallet); // { card: 3, money: { mother: 8000, mine: 100 } }
console.log(friend2_wallet); // { card: 3, money: { mother: 8000, mine: 100 } }
어라! 복사하면 참조 문제는 발생하지 않는것 아니었나요?
자, 여기서 이제 "얕은 복사" 라는 개념이 나온다.
Object.assign()은 얕은 복사를 해주는 메소드로 1Depth 까지만 그 특성을 유지해준다.
전개연산자도 이와 마찬가지다.
// 전개연산자 얕은복사 예시
const wallet = {
card: 3,
money: 0
};
const freind1_wallet = { ...wallet };
console.log(wallet); // { card: 3, money: 0 }
console.log(freind1_wallet); // { card: 3, money: 0 }
wallet.card = 4;
console.log(wallet); // { card: 4, money: 0 }
console.log(freind1_wallet); // { card: 3, money: 0 }
// 전개연산자 깊은복사...
const wallet = {
card: 3,
money: {
mother: 5000,
mine: 100
}
};
const freind1_wallet = { ...wallet };
console.log(wallet); // { card: 3, money: { mother: 5000, mine: 100 } }
console.log(freind1_wallet); // { card: 3, money: { mother: 5000, mine: 100 } }
wallet.money.mother += 3000;
console.log(wallet); // { card: 3, money: { mother: 8000, mine: 100 } }
console.log(freind1_wallet); // { card: 3, money: { mother: 8000, mine: 100 } }
이런 문제를 해결하려면 어떻게해야 할까?
늘 그렇듯 방법이 있다.
1. 재귀함수를 통한 복사
2. JSON 메소드 응용하기
3. lodash등 라이브러리르 이용하기
1. 재귀함수를 통한 복사는 빈 객체를 생성하고 for...in 함수로 객체의 key,value를 빈 객체에 집어넣는 방식이다.
프로젝트 내에 deepCopy함수를 하나 생성해두고 두고두고 쓰면 제법 유용하다.
function deepCopy(obj) {
const newObj = {};
for (let key in obj) {
if (typeof obj[key] === 'object') {
newObj[key] = deepCopy(obj[key]);
} else {
newObj[key] = obj[key];
}
}
return newObj;
}
2. JSON 메서드를 응용하는 방법은 간편하지만 퍼포먼스 적으로 좋지않다고 한다. 또한, File 타입 복사간 문제가 발생하니 사용을 지양하는게 좋을것으로 생각된다.
const obj = {
a: 1,
b: {
b_1: 2,
b_2: 3,
}
}
const copiedObj = JSON.parse(JSON.stringify(obj));
3. lodash 등 라이브러리 사용하기는 쉽고 강력하므로 개인적으로 이 방식을 권장하는바이다.
import _ from 'lodash';
const obj = {
a: 1,
b: {
b_1: 2,
b_2: 3,
}
}
const copiedObj = _.cloneDeep(obj);
'개발, 코딩 > Javascript' 카테고리의 다른 글
[JS/OOP] 1. 객체지향 프로그램의 의미를 알아보자. (0) | 2021.12.09 |
---|---|
이미지 로드, 부드럽게 처리하기 (js + css + react) (0) | 2021.07.13 |
Javascript: 브라우저 닫히기 전, 새로고침 전 이벤트 (0) | 2021.03.17 |
Input, number type의 숫자 롤링을 없애보자 (0) | 2021.02.22 |
간단한 정규식 모음 (휴대 전화번호) (0) | 2020.11.12 |