기술면접으로 나온 내용중 얕은복사와 깊은복사에 대해 정리하려고 한다.
자바스크립트는 기본 자료형(숫자, 문자열, boolean)의 값을 복사할 때 값을 완전히 복사한다. 따라서 =을 이용하여 값 복사를 쉽게 할 수 있다.
let originalValue = 100;
let newValue = originalValue;
originalValue = 200;
console.log(originalValue);
console.log(newValue);
위 소스코드 1열에서 originalValue에 100의 값이 들어가고, 2열에서 newValue에 100이라는 값이 복사되어, 아래 그림과 같이 두개의 변수 OriginalValue, NewValue는 완전히 독립적인 상태가 된다.
이 상태에서 4열에 따라 originalValue의 값을 200으로 변경하면, originalValue 값만 200이 된다.
이렇게 두 변수가 완전히 독립성을 갖는 것을 '값 복사' 또는 '깊은 복사'라고 한다.
값을 복사하고 변경했을 때, 다른 값에 전혀 영향을 주지 않는다.
객체에 변수를 저장하면, 실제 값을 저장하는 것이 아니라 객체를 메모리 어딘가에 만들고, 객체의 참조(위치값)를 저장하게 된다.
따라서 객체(배열 포함)의 경우 =를 이용하여 복사하면, 참조 복사만 가능하다.
let originalArray = [1,2,3,4];
let newArray = originalArray;
originalArray[0] = 200;
console.log(originalArray);
console.log(newArray);
1열에서 배열 originalArraydp [1,2,3,4]를 저장하는 과정은 다음과 같다.
주소값 0x10에 [1,2,3,4]를 저장하고, 객체 originalArray는 '0x10'위치를 참조.
이때 2열에 따라 참조되는 위치값 '0x10'이 복사된다.
4열에서 originalArray[0]=200;을 실행하면, 참조되는 위치 0x10의 값이 변경된다.
originalArray와 newArray는 같은 메모리 위치를 참조하게 된다.
따라서 두 배열은 독립적이지 않다. 이것을 '참조 복사' 또는 '얕은 복사'라고 한다.
6,7열에 따라 newArray[0]을 출력하면 둘 다 200을 출력한다.
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값과 동일하다.
얕은 복사 처럼 주소를 복사하여 공유하는것이 아니라, 새로운 객체안 속성만 복사해서 사용하는것.
const obj1 = {a:1, b:2};
const obj2 = {...obj};
obj2.a = 100;
console.log(obj1 === obj2) // false
console.log(obj1.a) //1
https://developer.mozilla.org/ko/docs/Web/JavaScript/Reference/Global_Objects/Object/assign
Object.assign()메소드 사용법(MDN)
const obj1 = { a:1, b:2 };
const obj2 = Object.assign({}, obj1);
obj2.a = 100;
console.log( obj1 === obj2 ) // false
console.log( obj1.a) //1
-Object.assign() 메소드를 통해 첫 번째 인자로 {}객체를, 두 번째 인자로 obj1 넣고 obj2에 할당
참고: Spread 문법은 배열을 복사할 때 1 레벨 깊이에서 효과적으로 동작합니다. 그러므로, 다음 예제와 같이 다차원 배열을 복사하는것에는 적합하지 않을 수 있습니다. (Object.assign() 과 전개 구문이 동일합니다)
- Object.assign() 메소드와 spread 연산자 둘 다 완벽한 Deep Copy가 되지 않는다
- 객체가 서로 다르다고 깊은 복사가 이루어진건 아니다.
- 1 depth까지는 확실하게 Deep Copy
- 2 depth 이상이면 Shallow Copy
const obj1 = { a: {b:1, c:1}, d:2};
const obj2 = { ...obj1, a:{...obj1.a} };
obj1.a.b = 100;
console.log(obj1 === obj2) //false
console.log(obj2.a.b) // 1
function clone(obj) {
let output = {};
for(let i in obj{
output[i] = obj[i];
}
return output;
}
let original = {a: 10, b: 20}; // 원본 객체
let regerenced = original; // 얕은 복사 객체
let cloned = clone(original) // 깊은 복사 객체
original.a = 20;
console.log(JSON.stringfy(referenced, null, 2));
console.log(JSON.stringfy(cloned, null, 2));
끝.
해당 내용은 아래의 링크에서 참조하였다.
https://hanamon.kr/javascript-shallow-copy-deep-copy/
https://wanna-b.tistory.com/18