티스토리 뷰

// 참조형 복사하기 (Reference Type Copy)
let numbers1 = [1, 2, 3];
let numbers2 = numbers1;

numbers2.push(4);

console.log(numbers1); // [1, 2, 3, 4]
console.log(numbers2); // [1, 2, 3, 4]

참조형 값은 변수에 할당될 때 값 자체가 아니라 주소값이 할당됩니다. 그래서 이 코드를 보면 배열도 참조형이기 때문에 numbers1에 이 배열의 주소값이 할당이 되고 numbers2에서도 numbers1이 가지고 있는 배열의 주소값이 복사가 돼서 numbers2만 변경했지만 이 코드를 실행했을 때 numbers1도 변경된 모습을 확인할 수 있습니다.

 

그런데 상황에 따라서는 이 참조형 값을 그대로 복사하고 싶을 수 있습니다.

말 그대로 numbers2만 변경하고 싶을 때 배열의 경우에는 이렇게 slice 메소드를 호출할 때 파라미터로 아무런 값도 전달하지 않으면 원래 값이 그대로 리턴되는 특성을 활용해서 마치 배열을 복사하는 것과 같은 효과를 얻을 수 있습니다. 이대로 코드를 실행해보면 number2만 변경이 된 것을 확인할 수 있습니다.

// 참조형 복사하기 (Reference Type Copy)
let numbers1 = [1, 2, 3];
let numbers2 = numbers1.slice();

numbers2.push(4);

console.log(numbers1); // [1, 2, 3]
console.log(numbers2); // [1, 2, 3, 4]

객체의 경우 코드를 보면 이렇게 첫 번째 course 데이터를 담은 객체가 있고 이 객체를 복사해서 title만 바꿔줬지만 이 코드를 그대로 실행해보면 course1도 title이 변경된 것을 확인할 수 있습니다. 

// 참조형 복사하기 (Reference Type Copy)
let course1 = {
  title: '파이썬 프로그래밍 기초',
  language: 'Python'
};
let course2 = course1;

couse2.title = '알고리즘의 정석';

console.log(course1); // {title:'알고리즘의 정석', language:'Python'}
console.log(course2); // {title:'알고리즘의 정석', language:'Python'}

객체에는 slice 같은 메소드가 없습니다.

사실 객체도 JavaScript에서 미리 만들어둔 Object라는 객체의 assign 메소드를 활용하면 복사를 할 수 있습니다. 실행해 보면 이렇게 course2만 title이 변경된 것을 확인할 수 있습니다. 

// 참조형 복사하기 (Reference Type Copy)
let course1 = {
  title: '파이썬 프로그래밍 기초',
  language: 'Python'
};
let course2 = Object.assign({}, course1);

couse2.title = '알고리즘의 정석';

console.log(course1); // {title: 'Python'}
console.log(course2); // {title:'알고리즘의 정석', language:'Python'}

직관적으로 이해하기 위해 메소드를 활용하지 않고 for...in문으로 객체를 한번 복사해보겠습니다. course2에는 빈 객체를 만든 다음에 이렇게 course1으로 for...in문을 작성해서 각 프로퍼티들을 넣어주면 똑같은 프로퍼티를 가지고 있지만 서로 독립적인 객체로 복사를 할 수가 있습니다. 

저장하고 실행해 보면 이번에도 course2의 title만 바뀐 것을 확인할 수 있습니다.

그런데 여기에 for문은 너무 course1과 course2에만 한정적입니다. 그래서 만약에 course3이나 4가 생긴다면 또 for문을 작성해야합니다. course2에 이 함수를 호출하는 값을 변수에 할당해 주게 되면 

// 참조형 복사하기 (Reference Type Copy)
let course1 = {
  title: '파이썬 프로그래밍 기초',
  language: 'Python'
};
let course2 = {};

for (let key in course1){
  course2[key] = course1[key]
}

couse2.title = '자료 구조';

console.log(course1); // {title: 'Python'}
console.log(course2); // {title:'알고리즘의 정석', language:'Python'}

그래서 이렇게 함수로 만들어주고 함수를 사용해야 하니까 맨 위로 올려주면 훨씬 더 효율적인 코드로 활용할 수 있습니다.

이 함수를 보면 파라미터로 복사할 객체를 전달받고 그리고 임시로 빈 객체를 만든 다음 방금 한 것처럼 for...in문을 통해서 객체를 복사하고 임시 객체를 리턴해 줍니다. 그래서 course2에 이 함수를 호출하는 값을 변수에 할당해 주게 되면 이렇게 복사된 객체가 이 변수에 담기게 됩니다.

그렇게 되면 이 함수를 통해서 만약 course3이 생길 때도 이 함수를 활용할 수 있고 아니면 코드를 작성하다가 다른 객체를 복사해야할 때도 이 파라미터만 변경하면 되니까 훨씬 더 효율적으로 활용할 수 있습니다. 

// 참조형 복사하기 (Reference Type Copy)
function cloneObject(object){
  let temp = {};
  for (let key in object){
     temp[key] = object[key];
  }
  return temp;
}

let course1 = {
  title: '파이썬 프로그래밍 기초',
  language: 'Python'
};

let course2 = cloneObject(course1);

couse2.title = '자료 구조';
couse3.title = '객체 지향 프로그래밍';

console.log(course1); // {title: 'Python'}
console.log(course2); // {title:'알고리즘의 정석', language:'Python'}

그런데 여기서도 한 가지 주의해야 할 점이 있습니다.

여기 이렇게 선이수 과목을 넣은 다음에 코드를 실행해 보면 분명 앞서 만든 함수를 통해서 객체를 잘 복사했는데 course1에도 선이수 과목으로 파이썬 프로그래밍 기초가 추가된 것을 확인할 수 있습니다. 왜냐하면 선이수 과목 프로퍼티가 배열이기 때문에 또 주소값이 복사돼 버린 것입니다.

이 문제는 배열의 slice 메소드나 오브젝트 객체의 assign 메소드나 모두 동일하게 발생하는 문제인데요.

// 참조형 복사하기 (Reference Type Copy)
function cloneObject(object){
  let temp = {};
  for (let key in object){
     temp[key] = object[key];
  }
  return temp;
}

let course1 = {
  title: '파이썬 프로그래밍 기초',
  language: 'Python',
  prerequisite: []
};

let course2 = cloneObject(course1);

couse2.title = '알고리즘의 정석';
couse2.prerequisite.push('파이썬 프로그래밍 기초');

console.log(course1); // {title: '파이썬 프로그래밍 기초', language:'Python', prerequisite: Array(1)}
console.log(course2); // {title:'알고리즘의 정석',language:'Python',prerequisite: Array(1)}

우리가 만든 함수를 이렇게 바꿔주면 문제는 해결되긴 합니다. 

// 참조형 복사하기 (Reference Type Copy)
function cloneObject(object) {
  if (object === null || typeof object !== 'object'){
    return object;
  }
}

let temp;
if(Array.isArray(object)){
  temp = [];
} else{
  temp = {};
}

for(let key of object.keys(object)){
  temp[key] = cloneObject(object[key])
}

return temp;

};


let course1 = {
  title: '파이썬 프로그래밍 기초',
  language: 'Python',
  prerequisite: []
};

let course2 = cloneObject(course1);

couse2.title = '알고리즘의 정석';
couse2.prerequisite.push('파이썬 프로그래밍 기초');

console.log(course1); // {title: '파이썬 프로그래밍 기초', language:'Python', prerequisite: Array(1)}
console.log(course2); // {title:'알고리즘의 정석',language:'Python',prerequisite: Array(1)}

 

공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
«   2025/03   »
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
글 보관함