본 글은 면접을 대비하여 MDN에 설명된 Shallow copy를 번역한 글입니다.
얕은 복사(shallow copy)로 인해 생겨난 객체는 *프로퍼티가 원본값 프로퍼티와 동일한 참조를 공유하는 복사본(이하 복사 값)입니다. 결과적으로, 원본값/복사 값 중 하나라도 바뀌면 다른 하나도 똑같이 바뀌게 됩니다. 이에 따라 원본값/복사 값이 우리가 원하지 않게 바뀔 수 있습니다. 이러한 동작은 원본값/복사 값이 서로 완전히 독립적인 깊은 복사(deep copy)와는 대조를 이룹니다.
*프로퍼티는 객체 안에 들어가 있는 한 쌍의 key value를 말합니다. ex: 객체: {프로퍼티이름: "프로퍼티값"}
얕은 복사의 경우, 객체의 기존 프로퍼티 값을 부분적으로 접근하여 변경하는 것과 기존값을 완전히 새로운 값으로 할당하는 것은 다르다는 점을 이해하는 것이 중요합니다.
const original = [
{
list: ['butter', 'flour'],
},
];
const copy = Object.assign({}, original);
copy[0].list = ['oil', 'flour'];
// original [{list: ['oil', 'flour']}];
// copy [{list: ['oil', 'flour']}];
예를 들어, 배열을 담은 객체를 얕은 복사하여 copy
객체를 만든 후, copy[0].list = ["oil", "flour"]
로 프로퍼티 값을 바꾸면 공유된 프로퍼티 값을 부분적으로 수정하였기 때문에 이에 상응하는 원본값의 프로퍼티 값도 바뀌게 됩니다.
copy[0] = { list: ['oil', 'flour'] };
// original [{list: ['butter', 'flour']}];
// copy [{list: ['oil', 'flour']}];
대신, copy[0] = {list:["oil", "flour"]}
이런 식으로 기존값을 완전히 새로운 값으로 할당하게 되면 원본값은 바뀌지 않습니다. 이 경우, 그저 원본값과 공유하고 있는 복사 값의 프로퍼티 값을 부분적으로 바꾼 것이 아니라 완전히 새로운 값을 copy[0]
복사 값 배열에만 할당하였기 때문입니다.
자바스크립트에서는 모든 built-in 객체 복사 연산자(object-copy operations)를 사용하여 얕은 복사를 만들어낼 수 있습니다. (전개 연산자, Array.prototype.concat(), Array.prototype.slice(), Array.from(), Object.assign(), Object.create())
다음 예를 보면, ingredients_list
배열 객체가 생성되고 이 객체를 복사하여 ingredients_list_copy
가 생성되었습니다.
let ingredients_list = [
'noodles',
{
list: ['eggs', 'flour', 'water'],
},
];
let ingredients_list_copy = Array.from(ingredients_list);
console.log(JSON.stringify(ingredients_list_copy));
// ["noodles",{"list":["eggs","flour","water"]}]
list
프로퍼티 값을 복사 값인 ingredients_list_copy
에서 바꾼다면 원본값인 ingredients_list
에 있는 list
프로퍼티 값도 바뀔 것입니다.
ingredients_list_copy[1].list = ["rice flour", "water"];
console.log(ingredients_list[1].list);
// Array [ "rice flour", "water" ]
console.log(JSON.stringify(ingredients_list));
// ["noodles",{"list":["rice flour","water"]}]
완전히 새로운 값을 복사 값인 ingredients_list_copy
의 첫 번째 요소에 할당한다면, 원본값 ingredients_list
의 첫 번째 값에는 아무런 변화도 주지 않을 것입니다.
ingredients_list_copy[0] = "rice noodles";
console.log(ingredients_list[0]);
// noodles
console.log(JSON.stringify(ingredients_list_copy));
// ["rice noodles",{"list":["rice flour","water"]}]
console.log(JSON.stringify(ingredients_list));
// ["noodles",{"list":["rice flour","water"]}]
MDN - 전개 연산자
MDN - Array.prototype.concat()
MDN - Array.prototype.slice()
MDN - Array.from()
MDN - Object.assign()
MDN - Object.create()