티스토리 뷰
// 참조형 복사하기 (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)}
'프론트엔드 > JavaScript' 카테고리의 다른 글
[자료형 심화] 16. 변수, 그땐 그랬지 (0) | 2022.10.28 |
---|---|
[자료형 심화] 14. const, 변수와 상수 사이 (0) | 2022.10.27 |
[자료형 심화] 10. 기본형과 참조형 (0) | 2022.10.25 |
[자료형 심화] 08. 문자열과 배열 사이 (0) | 2022.10.24 |
[자료형 심화] 07. 문자열 심화 (0) | 2022.10.24 |
- Total
- Today
- Yesterday
- 참조형 데이터
- 동적(dynamic) 언어
- foreach
- find
- redux-thunk
- 기본형 데이터
- EVERY
- 느슨한 타입(loosely typed)
- null
- 얕은복사
- undefined
- some
- map
- redux-middleware
- 비교 연산자
- redux middleware
- filter
- 타입변환
- redux thunk
- redux
- findindex
- 불변 객체
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
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 |