참조형 값은 변수에 할당될 때 값 자체가 아닌 주소값이 할당된다고 했을 때,
let number1 = [1, 2, 3]
let number2 = number1
number2.push(4)
console.log(number1);
console.log(number2);
▲ 코드를 보면 배열도 참조형이기 때문에 number1에 배열[1,2,3]의 주소값이 할당되고
number1이 가지고 있는 배열의 주소값이 복사가 돼서 number2만 변경했지만
코드를 실행하면 number1도 변경된 모습을 확인 할 수 있다.
그런데 상황에 따라서는 이 참조형 값을 그대로 복사해야 할 경우가 있다.
말 그대로 number2만 변경할 때의 경우인데,
이럴 때 배열의 경우에는 'slice' 메소드를 활용하면 해결할 수 있다.
let number1 = [1, 2, 3]
let number2 = number1.slice() //slice 추가
number2.push(4)
console.log(number1);
console.log(number2);
▲ slice 메소드를 호출할 때 파라미터 값을 전달하지 않으면
원래 값이 그대로 리턴되는 특성을 활용해서
마치 배열을 복사하는 것과 같은 효과를 얻을 수 있다.
실행해보면 number2만 변경된 것을 확인할 수 있다.
이번에는 객체로 살펴보자면..
let course1 = {
title: '파이썬',
language:'Python'
}
let course2 = course1
course2.title = '알고리즘'
console.log(course1);
console.log(course2);
▲첫 번째 course 데이터를 담은 객체를 복사해서 title만 바꿔줬지만
course1도 title이 변경된 것을 확인할 수 있는데,
객체에는 배열 처럼 slice를 사용할수 없지만
자바스크립트에서 Object라는 객체의 assign 메소드를 활용해서 복사를 할 수 있다.
assign 메소드
let course1 = {
title: '파이썬',
language:'Python'
}
let course2 = Object.assign({}, course1) // 추가
course2.title = '알고리즘'
console.log(course1);
console.log(course2);
이렇게 course2만 title이 변경된 것을 확인할 수 있다.
그런데 좀 더 직관적으로 이해하기 위해서
메소드를 활용하지 말고 for...in문으로 객체를 복사해보자면..
for...in문으로 객체 복사
let course3 = {
title: '파이썬',
language:'Python'
}
// let course2 = course1
//let course2 = Object.assign({}, course1)
let course4 = {} //빈 객체 생성
for(let key in course3){ //for...in문 생성
course4[key] = course3[key]
}
course4.title = '자료구조'
console.log(course3);
console.log(course4);
▲ 그냥 빈 객체를 만든 다음에 course1(course3)으로 for...in문을 작성해서 각 프로퍼티들을 넣어주면
똑같은 프로퍼티를 가지고 있지만 서로 독립적은 객체로 복사를 할 수 있다.
실행해보면 이번에도 title만 바뀐 것을 확인할 수 있다.
그런데 for문은 변수들(course)에만 한정적인 것 같아보인다.
변수가 점점 늘어나면 또 for문을 작성해야한다.
for문은 사용하되 함수로 만들어주게 바꿔보자면.. (함수 사용은 맨위로 올림)
function을 활용한 객체 복사
function cloneObject(object){ //파라미터로 복사할 객체를 전달
let temp = {} //빈 객체
for (let key in object){
temp[key] = object[key]
}
return temp
}
let course5 = {
title: '파이썬',
language:'Python'
}
// let course2 = course1
// let course2 = Object.assign({}, course1)
let course6 = {} //함수 호출
course4.title = '자료구조'
console.log(course5);
console.log(course6);
▲ 파라미터로 복사할 객체를 전달 받고
임시로 빈 객체를 만든 다음에 for...in문을 통해 객체를 복사하고 임시 객체를 리턴해 주고있다.
let course6 = cloneObject(course5) //함수 호출
▲ 그래서 course6(기존course2)에 함수를 호출하는 값을 변수에 할당해 주게 되면
복사된 객체가 변수에 담기게 된다.
함수를 생성하여 그 내부에 for...in문을 활용해,
이제는 course가 늘어나도 함수를 활용할 수 있게된다. 한번 자바스크립트를 복사해보자면..▼
function cloneObject(object){
let temp = {}
for (let key in object){
temp[key] = object[key]
}
return temp
}
let course5 = {
title: '파이썬',
language:'Python'
}
// let course2 = course1
// let course2 = Object.assign({}, course1)
let course6 = cloneObject(course5) //함수 호출
let course7 = cloneObject(course5) //함수 호출2
course6.title = '자료구조'
course7.title = '자바스크립트'
console.log(course5);
console.log(course6);
console.log(course7);
어떤 상황이던 간에 파라미터만 변경해주면 되니깐 훨씬 더 효율적으로 활용할 수 있다.
▼ 주의할점(배열 프로퍼티 추가 관련)
function cloneObject(object){
let temp = {}
for (let key in object){
temp[key] = object[key]
}
return temp
}
let course8 = {
title: '파이썬',
language:'Python',
test : [] // 배열 추가
}
// let course2 = course1
// let course2 = Object.assign({}, course1)
let course9 = cloneObject(course8)
course9.title = '자료구조'
course9.test.push('배열추가test') //객체복사
console.log(course8);
console.log(course9);
▲ test 프로퍼티에 배열을 추가해서 객체를 복사하려고 했는데
'배열추가test'가 추가된 것을 확인할 수 있다.
왜냐하면 test 프로퍼티가 배열이기 때문에 또 주소값이 복사돼 버린 것이다.
이러한 문제는 앞서 살펴봤던 배열의 slice 메소드나 object 객체의 assign 메소드나
모두 동일하게 발생하는 문제이며
객체나 배열 안에 중첩해서 객체나 배열이 있는 경우에는 복사할 때
또 주소값이 복사되기 때문에 예상치 못한 결과를 얻을 수 있어서
그러므로.. 일단은 이러한 문제가 있다는 것만 인지하자.
★GitHub 주소 (참조형 copy)
★Notion 주소 (배열 추가 및 수정하기)
https://purrfect-gargoyle-935.notion.site/115e9530b3e180eb861fefd32891f7ec?pvs=4
'JS' 카테고리의 다른 글
(1) Interactive JavaScript - id,class tag select (0) | 2024.10.07 |
---|---|
(40) JavaScript - 자료형(심화) / const, 변수&상수 간단이론 (0) | 2024.10.04 |
(38) JavaScript - 자료형(심화) / 기본형과 참조형 (0) | 2024.10.04 |
(37) JavaScript - 자료형(심화) / 문자열 접근 (0) | 2024.10.03 |
(36) JavaScript - 자료형(심화) / 자바스크립트의 옥에 티 (0) | 2024.10.02 |