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에 있는 프로퍼티들을 변형하여 만들 수 있다.
위 코드의 결과 값은 아래의 그림처럼 나온다.
하지만 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);
ㄴㄴㄴ!!!
아니였다....
객체 안에 배열이 들어갔기 때문에 복사할 때는 또 그 배열의 주소 값이 복사된다.
이 경우 function cloneObject 안의 내용을 복잡하게 바꾸어주면 되긴 한데
아직 거기까지는 이해가 안간다...
일단!
객체를 복사하기 위해 for in 문을 사용했고 객체 안에 배열이 들어 있는 경우 또 코드를 추가해줘야 한다는 것만 알아두자.
다음 글에서는 실전 예제를 풀며 정리해보자!!!