웹/JavaScript
[Js] js에서는 얕은복사(shallow copy) ,깊은 복사(deep copy)가 어떻게 이루어질까?
wonin
2022. 10. 22. 11:41
포인터의 개념을 다시 되새기기 위해서 js에서 얕은 복사와 깊은 복사를 알아보겠습니다.
원시 타입에는 Number, BigInt, String, Boolean, Null, Undefined, Symbol 7개의 타입이 있습니다.
그 외 모든 데이터는 객체 타입입니다.
❗️얕은 복사(shallow copy)란?
const obj1 = { a: 1, b: 2};
const obj2 = obj1;
console.log( obj1 === obj2 ); // true
- 위의 예시처럼 객체를 직접 대입하는 경우 참조에 의한 할당이 이루어지므로 둘은 같은 데이터(주소)를 가지고 있습니다.
- 이것이 얕은 복사
const obj1 = { a:1, b:2 };
const obj2 = obj1;
obj2.a = 100;
console.log( obj1.a ); // 100
- 위 두 객체는 같은 데이터(주소)를 가지고 있고, 그래서 같은 주소를 참조합니다.
- 때문에 obj2의 property를 수정하고, obj1를 출력해도 obj2 값과 동일합니다.
👉 방법 1. …(spread) 연산자를 통한 복사
const obj1 = { a:1, b:2 };
const obj2 = { ...obj };
obj2.a = 100;
console.log( obj1 === obj2 ) // false
console.log( obj1.a ) // 1
- ...(spread) 연산자를 통해 { }안에 obj1의 속성을 복사하여 obj2에 할당합니다.
- 이제 obj1과 obj2는 다른 주소를 갖게됩니다. (그러나 딱, 1 depth 까지만)
- 값이 변하지는 않았습니다. 완벽한 깊은 복사가 안된것이죠
Object.assign(생성할 객체, 복사할 객체)도 depth 1까지만 복사가 됩니다.
const object = {
a: "a",
number: {
one: 1,
two: 2,
},
};
const copy = Object.assign({}, object);
copy.number.one = 3;
console.log(object === copy); // false
console.log(object.number.one === copy.number.one); // true
Array.prototype.slice() 도 depth 1까지만 복사가 됩니다.
const original = ['a',2,true,4,"hi"];
const copy = original.slice();
console.log(JSON.stringify(original) === JSON.stringify(copy)); // true
copy.push(10);
console.log(JSON.stringify(original) === JSON.stringify(copy)); // false
console.log(original); // [ 'a', 2, true, 4, 'hi' ]
console.log(copy); // [ 'a', 2, true, 4, 'hi', 10 ]
❗️깊은 복사(deep copy)란?
얇은 복사 처럼 주소를 복사해서 공유하는 것이 아니라, 아예 새로운 객체안 속성(property)만 복사 해서 사용할 수 없을까?
👉 방법 1. JSON.parse && JSON.stringify을 활용한 복사
JSON.stringify()는 객체를 json 문자열로 변환하는데 이 과정에서 원본 객체와의 참조가 모두 끊어집니다.
객체를 json 문자열로 변환 후, JSON.parse()를 이용해 다시 원래 객체(자바스크립트 객체)로 만들어줍니다.
이 방법이 가장 간단하고 쉽지만 다른 방법에 비해 느리다는 것과 객체가 function일 경우, undefined로 처리한다는 것이 단점입니다.
var objA = [{ id: 1, name: "david" }];
var objB = JSON.parse(JSON.stringify(objA[0]));
objB.name = "jeff";
console.log("objB--", objB); // { id: 1, namve: 'jeff' }
console.log("objA--", objA); // [ { id: 1, name: 'david' } ]
👉 방법 2. lodash 라이브러리를 사용하기
라이브러리를 설치해야합니다. 더 쉽게 깊은 복사를 할 수 있습니다.
const deepCopy = require("lodash.clonedeep")
const object = {
a: "a",
number: {
one: 1,
two: 2,
},
arr: [1, 2, [3, 4]],
};
const copy = deepCopy(object);
copy.number.one = 3;
copy.arr[2].push(5);
console.log(object === copy); // false
console.log(object.number.one === copy.number.one); // false
console.log(object.arr === copy.arr); // false
console.log(object); // { a: 'a', number: { one: 1, two: 2 }, arr: [ 1, 2, [ 3, 4 ] ] }
console.log(copy); // { a: 'a', number: { one: 3, two: 2 }, arr: [ 1, 2, [ 3, 4, 5 ] ]
기존 object와 copy한 객체의 참조주소, 메모리에 있는 값들이 아예 달라지는 것을 확인할 수 있습니다.
출처
728x90