본문 바로가기
카테고리 없음

JavaScript 기초 : 자료형 업그레이드 5. 참조형 복사

by 조크리 2020. 9. 15.
반응형

 

5. 참조형 복사하기

 

지난 글에서 확인했던 글처럼 참조형을 복사하면 참조형으로 가는 주소가 복사된다. 

JavaScript 기초 : 자료형 4. 기본형과 참조형

 

아래의 예시 코드를 보자. 

numbers1에 배열을 할당했고  numbers2는 numbers1을 할당했다. 

그리고 numbers2의 마지막 값에 4를 추가하였는데 결과는 어떻게 될까?

//참조형 복사하기
let numbers1 = [1, 2, 3];
let numbers2 = numbers1;

numbers2.push(4);

console.log(numbers1);
console.log(numbers2);

당연히

numbers1과 numbers2 모두

 

[ 1, 2, 3, 4] 

 

가 출력된다. 

 

그럼 number2 배열만 4 값을 추가하여 출력하고 싶다면 어떻게 하면 될까?

 

이럴 때는

slice 매소드를 사용하면 된다!

 

5-1. slice메소드로 참조형 복사하기

slice메소드는 파라미터 값으로 아무 것도 넣지 않으면 값이 복사되는 특징이 있다.

따라서 numbers2에 numbers1.slice()를 할당해주면 그 값이 복사된다.

//참조형 복사하기(slice메소드 이용)
let numbers1 = [1, 2, 3];
let numbers2 = numbers1.slice();

numbers2.push(4);

console.log(numbers1);
console.log(numbers2);

 

그래서 이 경우 number2에만 4가 추가되어

[ 1, 2, 3 ]

[ 1, 2, 3, 4 ]

이 출력되게 된다. 

 

 

그럼 객체는 어떻까? 객체는 slice메소드가 없다. 

객체는 Object.assign(target, ... sources) 이라는 메소드를 활용하면 된다. 

 

Object.assign(target, ... sources)메서드를 살펴보자.

첫 번째 파라미터는 타켓이며 두 번째 인자부터 마지막 인자까지는 소스 오브젝트이다. 

소스 오브젝트는 타켓 오브젝트에 병합되고 리턴값으로 타겟 오브젝트를 반환한다. 

 

즉,  두 번째 파라미터로 쓰인 오브젝트가 첫 번째 파라미터로 쓰인 오브젝트로 반환된다는 말이다.

예시를 살펴보자.

course1은 프로퍼티가 2개 있는 객체이다. 

course2는 course1을 복사할 것인데 이 때 Object.assign를 이용한다.

// 객체 Object.assign 메소드 활용하기

let course1 = {
  title : '자바스크립트',
  language : 'JavaScript'
};

let course2 = Object.assign({}, course1);

course2.title = '프로그래밍 언어';

console.log(course1);
console.log(course2);

이 경우 Object.assign의 첫 번째 파라미터로 객체 리터럴 { } 이 들어왔다. 

그리고 두 번째 파라미터로는 course1이 들어왔는데 첫 번째 파라미터인 빈 객체 안에 병합된다. 

 

따라서 그 결과 값은 아래 그림처럼 출력된다. 

course2는 course1을 복사한 것이고, course2의 title프로퍼티 값만 바뀐 것을 볼 수 있다. 

 

 

그럼 Object.assign을 쓰지 않고

for in 문으로 객체를 복사하는 코드를 확인해보자!

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

let course1 = {
  title : '자바스크립트',
  language : 'JavaScript'
};

let course2 = cloneObject(course1);
let course3 = cloneObject(course1);

course2.title = '프로그래밍 언어';
course3.language = 'python'

console.log(course1);
console.log(course2);
console.log(course3);

매번 course를 추가할 때마다 for in문을 써주기 힘드니까 for in 문이 포함된 function cloneObject를 만든다.

function안을 살펴보면 일단 임시 temp 객체를 하나 만들고 

이 temp에 for in문으로 course1의 내용을 복사하게 한다. 

그리고 temp를 리턴한다.

 

이렇게 만들어 놓으면 course2, 3, 4 등 만들고 싶은 course를 course1에 있는 프로퍼티들을 변형하여 만들 수 있다. 

위 코드의 결과 값은 아래의 그림처럼 나온다. 

course 2와 course3이 잘 복사되고 변형됨.

 

 

하지만 course1객체 안에 배열이 있다면 어떨까?

단순한 프로퍼티 값들이 아닌

배열일 경우에도 잘 작동이 될까?

 

아래의 경우는 course1에 배열이 포함되었을 때 course2에서 그 배열 값을 바꾸는 코드이다. 

course2만 잘 바뀌게 될까?

//참조형 복사하기(객체 안에 배열이 있는 경우 또 주소 값 복사)
function cloneObject(object) {
  let temp = {};
  for (let key in object) {
    temp[key] =object[key];
  }
  return temp;
};

let course1 = {
  title : '자바스크립트',
  language : 'JavaScript',
  level : []
};

let course2 = cloneObject(course1);
course2.title = '프로그래밍 언어';
course2.level.push('3');

console.log(course1);
console.log(course2);

course1과 course2의 level이 3으로 똑같다. 

 

ㄴㄴㄴ!!!

아니였다....

객체 안에 배열이 들어갔기 때문에 복사할 때는 또 그 배열의 주소 값이 복사된다. 

 

이 경우 function cloneObject 안의 내용을 복잡하게 바꾸어주면 되긴 한데

 

아직 거기까지는 이해가 안간다...

 

일단!

객체를 복사하기 위해 for in 문을 사용했고 객체 안에 배열이 들어 있는 경우 또 코드를 추가해줘야 한다는 것만 알아두자. 

 

다음 글에서는 실전 예제를 풀며 정리해보자!!!

 

 

 

 

반응형