2022. 8. 11. 22:58ㆍJavaScript
최근 JavaScript로 알고리즘 문제를 풀다가 Array를 deep copy를 한 것 같은데 계속 shallow copy가 되어 직접 찾아보았고 다시 정리하고자 합니다.
JavaScript에는 포인터라는 개념이 없기에 포인터 변수라는 말보다는 객체 또는 배열이라는 말로 대체하여 설명하겠습니다. 예제는 배열로 할 예정입니다.
틀린 부분이 있다면 말씀해 주시면 감사하겠습니다.
Shallow Copy(얕은 복사)란?
'주소값'을 복사하는 것입니다. 처음 들으면 잘 이해가 안 될 것이니 예제와 좀더 자세한 설명을 하자면 두 개 이상의 객체 또는 배열이 서로 같은 주소 값을 가리키는 것을 의미하며 주소값에 있는 값이 바뀌면 그 주소값을 가지고 있는 객체 또는 배열을 불러올 시 바뀐 값을 반환합니다.
일반적으로 JavaScript에서 객체 또는 배열을 바로 다른 변수에 집어 넣으면 Call-by-Reference로 주솟값을 준다. 그리하여 값을 바꾸고 그 주소를 가리키고 있던 다른 객체 또는 배열로 부르면 바뀐 값을 반환한다는 것을 확인할 수 있습니다.
아래의 예제를 보면 쉽게 알 수 있습니다.
let arr1 = [1,2,3];
let arr2 = arr1;
arr2[0] = 4;
console.log(arr1[0]) /// 4
Deep Copy(깊은 복사)란?
'실제값'을 새로운 메모리 공간에 복사하는 것을 의미합니다. shallow copy와는 다르게 Call-by-Value로 새로운 객체 또는 배열을 만들어 주소값이 아닌 새로이 실제값을 다시 넣어 복사하는 행위를 하는겁니다.
아래의 예제를 보면 쉽게 알 수 있습니다.
let arr1 = [1,2,3];
let arr2 = arr1.slice();
arr2[0] = 4;
console.log(arr1[0]) /// 1
JavaScript에서 변수는 일반적으로 Deep Copy가 되며 Object 또는 Array는 Shallow Copy가 일어납니다.
그렇다면 Object와 Array는 어떻게 Deep Copy를 방법을 알아보겠습니다.
JSON.parse, JSON.stringify 사용
let obj1 = [1,2,3];
let obj2 = JSON.parse(JSON.stringify(obj));
console.log(obj1===obj2); /// false
모든 depth가 deep copy됩니다. Object와 Array 둘다 적용이 가능합니다.
이후 아래의 방법들은 depth가 1개만 되는 불완전한 deep copy 방법입니다.
각각의 depth마다 적용해 주어야 완벽히 deep copy가 됩니다.
1) Object와 Array 둘다 되는 버전(1) (spread operator)
let arr1 = [1,2,3];
let arr2 = [...arr1];
console.log(arr1===arr2); ///false
2) Object와 Array 둘다 되는 버전(2)
JavaScript에서는 Array도 Object입니다. (2023년 02월 18일 수정)
let obj1 = { a:1, b:2 };
let obj2 = Object.assign({}, obj1);
console.log(obj1===obj2); ///false
3) Array만 되는 버전
let arr1 = [1,2,3];
let arr2 = arr1.slice();
console.log(arr1===arr2) ///false
위의 경우 depth가 1까지만 적용되고 더 많은 depth를 사용하려고 할 경우 각각 depth에서 deep copy를 해야합니다.
필자의 경우 2D Array를 deep copy를 해야했지만 depth가 1일 때와 Array만 되는 버전인 3번 방식을 이용했기에 deep copy가 되었다고 생각을 했습니다.
하지만 중간에 계속 shallow copy가 되어서 어디가 에러가 발생했는지 찾기 어려웠습다. 이에 평소에 JSON.parse, JSON.stringify을 사용해야겠다는 생각이 들었습니다.
Reference
https://developer.mozilla.org/en-US/docs/Glossary/Deep_copy
Deep copy - MDN Web Docs Glossary: Definitions of Web-related terms | MDN
A deep copy of an object is a copy whose properties do not share the same references (point to the same underlying values) as those of the source object from which the copy was made. As a result, when you change either the source or the copy, you can be as
developer.mozilla.org
https://hanamon.kr/javascript-shallow-copy-deep-copy/
[JavaScript] 얕은 복사(shallow copy) vs 깊은 복사(deep copy) - 하나몬
💡 얕은 복사(shallow copy) vs 깊은 복사(deep copy) ❗️얕은 복사(shallow copy)란? const obj1 = { a: 1, b: 2}; const obj2 = obj1; console.log( obj1 === obj2 ); // true 위의 예시처럼 객체를 직접 대입하는 경우 참조에 의
hanamon.kr
Create copy of multi-dimensional array, not reference - JavaScript
This is also referred to as "deep copying", which I've found some articles on. Closest seems to be this one but it's for jQuery - I'm trying to do this without a library. I've also seen, ...
stackoverflow.com
https://developer.mozilla.org/ko/docs/Web/JavaScript/Reference/Global_Objects/Object/assign
Object.assign() - JavaScript | MDN
Object.assign() 메서드는 출처 객체들의 모든 열거 가능한 자체 속성을 복사해 대상 객체에 붙여넣습니다. 그 후 대상 객체를 반환합니다.
developer.mozilla.org
'JavaScript' 카테고리의 다른 글
[JavaScript] 큰 숫자 변환 (0) | 2023.01.19 |
---|---|
JavaScript - 사용 및 데이터 타입 (0) | 2021.05.03 |