얕은 복사는 참조타입의 변수를 직접 대입해서, 같은 메모리 주소를 참조하게 되는 것을 의미한다.
// 초기 값을 가지는 init 객체
const init = {
name: '',
job: '',
};
// clone에 init 대입
const clone = init;
clone.name = '서나무';
clone.job = 'Frontend developer';
console.log(init);
console.log(clone);
코드를 실행시켜보면 clone
객체뿐 아니라 init
객체의 name
job
도 함께 변경되었다.
// 초기 값을 가지는 init 배열
const init = ['name', 'job'];
// clone에 init 대입
const clone = init;
clone[1] = 'game';
console.log(init);
console.log(clone);
코드를 실행시켜보면 clone
배열뿐 아니라 init
배열의 index1
에 해당하는 요소도 함께 변경되었다.
깊은 복사란 복사 대상 객체
에게 새로운 메모리에 할당해서 복사 소스 객체
와 다른 메모리 주소를 참조하도록 하는 것을 의미한다.
JavaScript에서 객체와 배열을 복사할 때, spread 연산자를 사용할 수 있다.
객체
const init = {
name: '',
job: '',
};
const clone = { ...init };
clone.name = '서나무';
clone.job = 'Frontend developer';
console.log(init);
console.log(clone);
코드를 실행시켜보면 clone
객체의 name
job
만 변경된 것을 볼 수 있다.
배열
const init = ['name', 'job'];
const clone = [...init];
clone[1] = 'game';
console.log(init);
console.log(clone);
코드를 실행시켜보면 clone
배열의 index1
에 해당하는 요소만 변경된 것을 볼 수 있다.
assign 함수는 첫번째 인자로 복사 대상 객체
를 넣어주고, 두번째 인자로 복사할 소스 객체
를 넣어주면 된다.
const init = {
name: '',
job: '',
};
const clone = Object.assign({}, init);
clone.name = '서나무';
clone.job = 'Frontend developer';
console.log(init);
console.log(clone);
코드를 실행시켜보면 clone
객체의 name
job
만 변경된 것을 볼 수 있다.
concat 함수는 빈 배열을 선언하고 복사 소스 배열
을 넣어주면 된다.
const init = ['name', 'job'];
const clone = [].concat(init);
clone[1] = 'game';
console.log(init);
console.log(clone);
코드를 실행시켜보면 clone
배열의 index1
에 해당하는 요소만 변경된 것을 볼 수 있다.
JavaScript에서 제공하는 전개 연산자, assign함수, concat함수는 치명적인 한계가 있다.
깊이가 1인 경우에만 깊은 복사가 되고, 깊이가 깊어지는 다차원 객체, 배열의 경우에는 얕은 복사가 된다는 것이다.
const init = {
name: '',
job: '',
use: {
lang: '',
},
};
const clone = { ...init };
clone.name = '서나무';
clone.job = 'Frontend developer';
clone.use.lang = 'JavaScript';
console.log(init);
console.log(clone);
코드 실행 결과
{ name: '', job: '', use: { lang: 'JavaScript' } } // ! 얕은 복사
{ name: '서나무', job: 'Frontend developer', use: { lang: 'JavaScript' } }
name
job
은 깊은 복사가 됐지만, use
객체의 lang
은 얕은 복사가 됐다.
외부 라이브러리를 사용하지 않고 다차원 객체, 배열을 깊은 복사를 해보자.
검색을 해보니 객체와 배열이 혼합된 형태의 깊은 복사를 할 수 있는 재귀 함수 예제가 없었다.
그래서 직접 재귀 함수를 구현해봤다.
const deepCopy = (target) => {
/**
* 객체를 받아서 깊은 복사 후 반환하는 재귀함수
* @param {Object} object 복사할 객체
* @returns {Object} 복사된 객체
*/
const deepCopyObject = (object) => {
if (object === null || typeof object !== 'object') return object;
const clone = {};
for (const key in object) {
if (Array.isArray(object[key])) {
clone[key] = deepCopyArray(object[key]);
} else {
clone[key] = deepCopyObject(object[key]);
}
}
return clone;
};
/**
* 배열을 받아서 깊은 복사 후 반환하는 재귀함수
* @param {Array} array 복사할 배열
* @returns {Array} 복사된 배열
*/
const deepCopyArray = (array) => {
if (array === null || !Array.isArray(array)) return array;
const clone = [];
for (let key = 0; key < array.length; key++) {
if (Array.isArray(array[key])) {
clone[key] = deepCopyArray(array[key]);
} else {
clone[key] = deepCopyObject(array[key]);
}
}
return clone;
};
if (typeof target === 'object' || Array.isArray(target)) {
return Array.isArray(target)
? deepCopyArray(target)
: deepCopyObject(target);
}
return target;
};
재귀 함수를 이용해서 다차원 객체를 깊은 복사 해보자.
const init = {
name: '',
job: '',
use: {
lang: '',
},
hobby: [
{
game: '',
},
],
};
const clone = deepCopy(init);
clone.use.lang = 'JavaScript';
clone.hobby[0].game = 'Crazy Arcade';
console.log(init);
console.log(clone);
코드 실행 결과
{ name: '', job: '', use: { lang: '' }, hobby: [ { game: '' } ] }
{
name: '',
job: '',
use: { lang: 'JavaScript' },
hobby: [ { game: 'Crazy Arcade' } ]
}
깊은 복사가 잘 되었고, 이는 객체 뿐 아니라 다차원 배열도 깊은 복사가 가능하다.
JSON 객체는 두 가지 메서드를 가지고 있다.
stringify
: javascript 값을 JSON으로 변환 후 반환parse
: JSON을 javascript 값으로 변환 후 반환복사할 소스 객체를 stringify
메서드로 JSON으로 만든 후 다시 parse
메서드로 javascript 값으로 변환하면 된다.
const init = {
name: '',
job: '',
use: {
lang: '',
},
};
const clone = JSON.parse(JSON.stringify(init));
clone.name = '서나무';
clone.job = 'Frontend developer';
clone.use.lang = 'JavaScript';
console.log(init);
console.log(clone);
JSON 객체의 메서드를 사용하는 것은 매우 느리다는 의견이 있어서 정말 그런지 궁금했다.
그래서 콘솔로 JSON 메서드와 내가 구현한 재귀 함수의 실행 시간을 출력해봤다.
const init = {
'depth1-1': {
dethp2: [
'depth3',
{
depth4: '',
},
[
{
'depth5-1': '',
'depth5-2': '',
'depth5-3': {
depth6: '',
},
},
],
],
},
'depth1-2': {
dethp2: [
'depth3',
{
depth4: '',
},
[
{
'depth5-1': '',
'depth5-2': '',
'depth5-3': {
depth6: '',
},
},
],
],
},
};
console.time('Custom recursion function');
const clone1 = deepCopy(init);
console.timeEnd('Custom recursion function');
console.time('JSON object');
const clone2 = JSON.parse(JSON.stringify(init));
console.timeEnd('JSON object');
내가 만든 재귀 함수가 훨씬 더 느리다. 🤣🤣
Lily had dabbled in poker with friends but had never participated in a serious tournament. Eager to test her skills, she entered a small online https://grandrushcasinoau.com/ poker tournament with a modest entry fee. The initial rounds were a whirlwind of nerves and excitement as Lily faced off against skilled opponents. She relied on her basic poker knowledge and intuition, making strategic decisions based on her opponents’ behavior.