깊은 복사와 얕은 복사의 차이,
깊은 복사를 할 수 있는 방법에 대해 정리해보고자 한다.
1. 깊은 복사 vs 얕은 복사
2. 깊은 복사 하는 방법
3. 얕은 복사 하는 방법
깊은 복사 vs 얕은 복사
쉽게 말하자면, 깊은 복사는 객체의 실제 값을 복사 하는 반면, 얕은 복사는 객체의 주소(reference)값을 복사한다.
원시 값(Number, String, Boolean, Null, undefined 등)을 복사 할 때에는 항상 깊은 복사가 되므로, 이 경우 깊은 복사와 얕은 복사를 구분할 필요가 없다.
이 구분이 중요해지는 시점은 참조 자료형(Object, Symbol, Array)을 다룰 때이다.
[ 얕은 복사 예시]
얕은 복사는 주소 값만 복사하고, 깊은 복사는 객체의 실제 값을 복사한다고 하였는데, 이 말이 어떤 의미를 가지는지 실제 예를 통해 살펴보자.
위 코드를 보면, 분명 brr 배열에만 1이라는 값을 push 해줬음에도 arr에도 같이 들어가 있는 것을 볼 수 있다.
이는 brr을 얕은 복사를 이용하여 만들었으며, arr, brr 두개의 변수는 하나의 주소값을 공유하고 있기 때문이다.
이러한 현상은 예시를 든 배열 뿐만 아니라 같은 주소형 자료인 객체에서도 똑같이 발생하게 된다.
[ 깊은 복사 예시]
자, 이제 깊은 복사는 어떤 것인지 알아보자.
얕은 복사와는 다르게, crr에 2라는 값을 push 했음에도, arr에는 어떠한 값도 들어있지 않았음을 알 수 있다.
이는 arr과 crr 이라는 배열이 서로 다른 주소값을 가지고 있음을 의미한다.
깊은 복사 하는 방법
1차원 배열 깊은 복사
여기에서 1차원 배열이라 함은 배열 안의 값이 전부 원시형 자료로 구성되어 있는 배열을 의미한다.
따라서, [1, 2, 3] 과 같은 배열은 해당 되지만, [{a: 1}, 2, 3]같은 배열은 해당되지 않는다.
1차원 배열의 경우, 다음 두가지 방법을 통해 간단히 깊은 복사를 할 수 있다.
1. Spread 연산자
아래처럼, 복사하고자 하는 배열을 spread 연산자를 통해 풀어서 생성하면 깊은 복사를 할 수 있다.
2. Array.prototpy.slice()
위에서 설명한 예시대로 slice() 메소드를 이용하면 깊은 복사를 할 수 있다.
1차원 객체 깊은 복사
여기에서 1차원 객체라 함은 객체안의 값이 전부 원시형 자료로 구성되어 있는 객체를 의미한다.
{a: 1, b: 2}와 같은 객체는 해당 되지만, {a: [1, 2, 3], b: 2}와 같은 객체는 해당되지 않는다.
1차원 객체의 경우, 다음 두가지 방법을 통해 간단히 깊은 복사를 할 수 있다.
1. spread 연산자
배열과 같으므로 자세한 설명은 생략한다.
2. Object.assign(생성할 객체, 복사할 객체)
2차원 이상 객체 깊은 복사
사실 내가 이 글을 포스팅 하는 가장 큰 이유이다.
위의 방법들을 통해 간단한 1차원 객체들은 깊은 복사가 가능하지만, 다차원의 경우 깊은 복사하기 까다로워진다.
이 방법은 크게 2가지로 나눌 수 있다.
1. JSON.stringify() && JSON.parse()
JSON.stringify 메소드는 JS 값이나 객체를 JSON 문자열로 변환한다(참고링크)
그리고 이때 원본객체와의 참조가 모두 끊어지게 된다.
JSON.parse 메소드는 JSON 문자열을 분석하여 JS 값이나, 객체로 변환한다.(참고링크)
즉, JSON.stringify()를 통해 참조(references)를 모두 제거하고,
다시 JSON.parse()를 통해 원래 객체 형태로 돌려놓는 방식인 것이다.
이 방식은 가장 간단하지만, 다른 방식에 비해 느리고, function인 경우 undefined로 나온다는 것이 단점이다.
2. 사용자 정의 함수
직접 함수를 구현하여 다차원 객체를 깊은 복사 할 수 있지만,
구현이 귀찮다는 단점이 있다.
const object = { a: "a", number: { one: 1, two: 2 }, arr: [1, 2, [3, 4]] };
function deepCopy(object) {
if (object === null || typeof object !== "object") {
return object;
} // 객체인지 배열인지 판단
const copy = Array.isArray(object) ? [] : {};
for (let key of Object.keys(object)) {
copy[key] = deepCopy(object[key]);
}
return copy;
}
const copy = deepCopy(object);
'JavaScript' 카테고리의 다른 글
원 그리기(각도로 원 좌표(x, y) 구하기) (0) | 2022.11.14 |
---|---|
[Solved] 쿠키 삭제가 안되는 문제 (cookies.remove doesn't work) (0) | 2022.10.14 |
Cookie 옵션 설정하기 (feat. iframe cookie 문제 해결) (0) | 2022.07.12 |
커링(Currying) Feat. 커링으로 로그 함수 구현 (0) | 2022.07.04 |
마우스 휠 이벤트 등록(js) (0) | 2022.06.29 |