자바스크립트에서 배열과 객체를 복사할 때, 얕은 복사와 깊은 복사를 구분하여 사용합니다.
얕은 복사
얕은 복사는 객체나 배열의 1단계 프로퍼티와 요소들만 복사하는 것을 말합니다. 객체나 배열 내부에 객체나 배열이 포함되어 있을 경우, 내부 객체나 배열은 참조 관계를 유지하게 됩니다.
얕은 복사는 배열의 slice() 메소드를 이용하여 구현할 수 있습니다.
const arr1 = [1, 2, [3, 4]]; const arr2 = arr1.slice(); // 얕은 복사
console.log(arr1[2] === arr2[2]); // true
위의 코드에서 arr1 배열을 slice() 메소드를 이용하여 복사하였습니다. arr2는 arr1과 같은 배열이지만, 내부의 배열 [3, 4]는 참조 관계를 유지하게 됩니다.
깊은 복사
깊은 복사는 객체나 배열의 모든 프로퍼티와 요소들을 재귀적으로 복사하는 것을 말합니다. 따라서 객체나 배열 내부에 객체나 배열이 포함되어 있어도, 모두 새로운 객체나 배열로 복사됩니다.
자바스크립트에서 깊은 복사를 구현하는 방법 중 하나는 Spread operator(...)를 이용하는 것입니다. Spread operator는 배열이나 객체의 요소나 프로퍼티들을 개별적으로 복사합니다.
1. 일반 배열의 깊은 복사
일반 배열을 깊은 복사하는 방법은 다음과 같습니다.
const arr1 = [1, 2, [3, 4]]; const arr2 = [...arr1]; // 깊은 복사
console.log(arr1[2] === arr2[2]); // false
위의 코드에서 Spread operator(...)를 이용하여 배열을 깊은 복사하였습니다. arr2는 arr1과 같은 배열이지만, 내부의 배열 [3, 4]는 복사된 새로운 배열로 대체되어 참조 관계를 유지하지 않습니다.
2. 일반 객체 배열의 깊은 복사
객체 배열을 깊은 복사하는 방법은 다음과 같습니다.
const arr1 = [{a: 1}, {b: 2}]; const arr2 = arr1.map(obj => ({...obj})); // 깊은 복사
console.log(arr1[0] === arr2[0]); // false
Spread operator(...)를 이용하여 깊은 복사를 하면서, 객체 배열의 요소인 객체들을 각각 새로운 객체로 복사하기 위해 map() 함수를 사용하였습니다.
3. 특수 객체 배열의 깊은 복사
하지만, 객체 배열 안에 객체가 다시 객체 배열을 포함하고 있거나, 함수를 포함하고 있는 경우, Spread operator나 map() 함수를 이용한 깊은 복사는 올바른 결과를 얻을 수 없습니다.
이 경우에는 JSON 객체의 parse()와 stringify() 메소드를 이용하여 깊은 복사를 해야 합니다. JSON 객체를 이용한 깊은 복사는 객체나 배열을 문자열로 변환하고, 다시 파싱하여 새로운 객체나 배열을 생성합니다.
3-1) 객체 배열 안의 객체가 다시 객체 배열을 포함하는 경우
const arr1 = [{a: 1, b: [2, 3]}, {c: 4}];
const arr2 = JSON.parse(JSON.stringify(arr1)); // 깊은 복사
console.log(arr1[0].b === arr2[0].b); // false
위의 코드에서 JSON.stringify() 메소드를 이용하여 배열을 문자열로 변환하고, JSON.parse() 메소드를 이용하여 새로운 배열을 생성하였습니다. arr2는 arr1과 같은 배열이지만, 내부 객체의 배열 [2, 3]는 참조 관계를 유지하지 않습니다.
3-2) 객체 배열 안의 객체가 함수를 포함하는 경우
const obj1 = { a: 1, b: () => console.log('hello') };
const obj2 = JSON.parse(JSON.stringify(obj1)); // 깊은 복사
console.log(obj1.b === obj2.b); // false
위의 코드에서 obj1 객체를 JSON.stringify() 메소드와 JSON.parse() 메소드를 이용하여 복사하였습니다. obj2는 obj1과 같은 객체이지만, 함수 b()는 복사되지 않아 참조 관계를 유지하지 않습니다.
따라서, 객체 배열 안의 객체가 다시 객체 배열을 포함하거나, 함수를 포함하고 있는 경우, Spread operator나 map() 함수 대신 JSON 객체를 이용하여 깊은 복사를 해야 합니다.
결론
자바스크립트에서 배열과 객체를 복사할 때, 얕은 복사와 깊은 복사를 구분하여 사용해야 합니다. 배열의 얕은 복사는 slice() 메소드를 이용할 수 있습니다.
배열과 객체의 깊은 복사는 Spread operator(...)를 이용하여 구현할 수 있습니다. 객체 배열의 깊은 복사는 map() 함수와 Spread operator를 이용하여 객체를 새로운 객체로 복사할 수 있습니다.
객체 배열 안의 객체가 다시 객체 배열을 포함하거나, 함수를 포함하고 있는 경우, Spread operator나 map() 함수 대신 JSON 객체를 이용하여 깊은 복사를 해야 합니다.
'Front-end > JavaScript' 카테고리의 다른 글
JS) not not 연산자 vs non-null assertion 연산자 (0) | 2023.03.02 |
---|---|
JS) Promise를 반환하는 함수의 다양한 표현 (fetch, axios) (0) | 2023.03.01 |
JS) then vs async/await ... (예시: fetch API) (0) | 2023.03.01 |
JS) fetch VS axios (API 호출) (0) | 2023.02.27 |
JS) [Alert] 웹 사이트에 경고 문구 띄우기 (0) | 2022.10.15 |