목차
- 얕은복사와 깊은복사
- 얕은복사와 깊은복사 예시
1. 얕은 복사와 깊은 복사
- 얕은 복사(Shallow Copy)
- 객체의 참조값(주소 값)을 복사
- 참조값을 복사할 때는 변수가 객체의 참조를 가리키고 있기 때문에 복사된 변수 또한 객체가 저장된 메모리 공간의 참조를 가리키고 있음 → 복사를 하고 객체를 수정하면 두 변수는 똑같은 참조를 가리키고 있기 때문에 기존 객체를 저장한 변수에 영향을 끼침
- 깊은 복사(Deep Copy)
- 실제 값을 복사
- 원시값을 복사할 때 그 값은 또 다른 독립적인 메모리 공간에 할당하기 때문에, 복사를 하고 값을 수정해도 기존 원시값을 저장한 변수에는 영향을 끼치지 않음
2. 얕은 복사와 깊은 복사 예시
얕은 복사 예시
Array.prototype.slice()
- start부터 end 인덱스까지 기존 배열에서 추출하여 새로운 배열을 리턴하는 메소드
- start와 end를 설정하지 않는다면, 기존 배열을 전체 얕은 복사
Object.assign()
- Object.assign(생성할 객체, 복사할 객체)
- 메소드의 첫 번째 인자로 빈 객체를 넣어주고 두 번째 인자로 복사할 객체
Spread 연산자 (전개 연산자)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44
//1. slice 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 ] //2. assign 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 //3. spread const object = { a: "a", number: { one: 1, two: 2, }, }; const copy = { ...object }; copy.number.one = 3; console.log(object === copy); // false console.log(object.number.one === copy.number.one); // true
깊은 복사 예시
참조형 데이터는 얕은 복사가 발생하기 때문에 별도의 처리가 필요
- 반복문을 이용한 방법
: 할당 이후에는 반복문을 통해 복사하고자 하는 데이터의 값을 하나씩 복사하면서 같은 값을 가진, 서로 다른 변수가 됨 전개 연산자를 이용한 방법
: 내부의 값들을 전개하여 새로운 데이터를 만들기에 깊은 복사가 되며, 반복문을 이용한 방법보다 짧은 코드로 구현 가능1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27
//1. 반복문 const arr1 = [1, 2, 3, 4, 5]; const arr2 = []; for (let i = 0; i < arr1.length; i++) { arr2.push(arr1[i]); } console.log(arr1 === arr2); // false; const obj1 = { name: "Tom", age: 5 }; const obj2 = {}; Object.keys(obj1).forEach((key) => { obj2[key] = obj1[key]; }); console.log(obj1 === obj2); // false; //2. 전개 연산자 const arr1 = [1, 2, 3, 4, 5]; const arr2 = [...arr1]; console.log(arr1 === arr2); // false; const obj1 = { name: "Tom", age: 5 }; const obj2 = { ...obj1 }; console.log(obj1 === obj2); // false;
- 반복문을 이용한 방법
원시형 데이터와 참조형 데이터에 따른 얕은 복사와 깊은 복사
→ 원시형 데이터는 기본적으로 깊은 복사가, 참조형 데이터는 얕은 복사가 발생원시형 데이터와 참조형 데이터가 메모리에 저장되는 방식이 서로 다름
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
let num1 = 123; let num2 = num1; console.log(num1 === num2); //true num2 = 456; console.log(num1 === num2); //false const obj1 = { name: "tom", age: 5 }; const obj2 = obj1; console.log(obj1 === obj2); //true obj2.name = "jerry"; console.log(obj1 === obj2); //true
이미지 출처 : https://nohack.tistory.com/30
원시형 데이터는 스택 메모리만 이용하고 메모리에 값 자체를 저장함
→ 원본을 새로운 변수에 할당하면 값을 복사하기에 완전히 새로운 값이 만들어짐
> 참조형 데이터는 스택 외에도 힙이라 하는 메모리를 사용하며, 이를 스택에서 참조하는 방식으로 동작함
→ 스택에는 힙을 가리키는 주소를 담게 되고, 원본을 새로운 변수에 복사하게 되면 스택에 담긴 메모리 주소를 복사하게 됨
→ 두 변수는 동일한 하나의 객체를 가리키게 되고 참조형 데이터의 특성으로 두가지가 모두 변경됨
출처