자료형의 종류에는 원시타입(Primitive type)과 객체 타입(Object type) 두 가지가 있다.
Boolean :true/false
null: 존재하지 않거나 유효하지 않은 주소 표시
undefined : 값이 할당되지 않은 상태
number: 정수, 실수 등의 숫자, 정수의 한계값이 있는데 2⁵³보다 크지 않는값, 이 값이 너머가면 bigint 타입으로 표현
string: 문자열(빈 문자열 포함)
symbol: 문자열과 함께 프로퍼티로 사용
객체는 객체겠거니 했던 과거를 반성하게 되는 내용을 배웠다.
let user={
name:"John",
age:27
}
위와같은 객체 타입을 보면서 'user에 name과 age의 값들이 각각 저장되는구나'라고 생각했는데 결코 그리 단순한 문제가 아니었다.
실질적으로 하나의 공간에(객체 안에) 두 개의 값을 저장할 수 없다. 그렇게 때문에 name의 "John"과 age의 27이 저장되어있는 메모리 공간을 가르키고 있는 주소값을 참조해서 불러오는 형태로 돌아간다.
object 복사란 것이 있다.
이것이야 말로 "객체를 복사해 보세요" 했다면 아주 처참하게 틀렸을 것이란 확신이 든다.
let user = {
name:"John",
age:27
}
let admin = user
위와 같이 내가 알던 방식으로 object를 복사한다면, admin을 수정할 때 user값도 동일하게 수정될 것이고, user를 수정한다면 마찬가지로 admin도 수정될 것이다.
그 이유는 바로 admin이 user의 참조하는 "주소값"을 복사했기 때문이다. admin은 복사된 주소를 통해 기존 user의 key와 value를 저장한 메모리를 가리키게 되는 것이다.
결론은 admin은 key와 value를 담은 메모리를 가리키고 있는 주소를 복사한 것이지, key와 value를 복사한 것이 아니라는 것이다.
이제 이렇게 하면 복사가 안 되는 것이구나라는 것을 알게 되었으니 실질적으로 복사할 수 있는 방법을 알아보자.
그 방법에는 얕은 복사(Shallow copy)와 깊은 복사(Deep copy)가 있다.
반복문 for문을 통한 객체 복사
let user = {
name:"John",
age:27
}
let admin = {}
for(let key in user){
admin[key] = user[key]
}
admin.name = "Park"
console.log(admin.name) //Park
console.log(user.name) //John
for문을 통해 탐색하며 하나하나 복사하는 방법이 있다
let user = {
name:"John",
age:27
}
let admin = Object.assign({}, user);
admin.name = "Park"
user.age = 30;
console.log(admin.name) //Park
console.log(user.name) // John
console.log(admin.age) //23
console.log(user.age) //30
Object.assign를 이용해 빈 배열에 user객체를 복사하여 admin에 넣어준다.
let user = {
name:"John",
age:27
}
//spread 연산자 사용
let admin = {...user}
admin.name = "Park"
user.age = 30;
console.log(admin.name) //Park
console.log(user.name) // John
console.log(admin.age) //23
console.log(user.age) //30
spread 연산자로 이렇게 간단하게 가능한다.
{...user} 이 안에 user.name, user.age 이 애들을 그냥 ...요걸로 퉁쳐서 불러오는 것이라니 어메이징
얕은 복사에는 치명적인 단점이 있었는데 그것은 바로! 객체 내에 또 다른 객체가 있다면 그 안쪽 객체는 복사되지 않는다는 것이다.
그렇다면 이쯤에서 꺼내볼 우리의 깊은 복사(Deep copy)
재귀 함수를 이용한 깊은 객체 복사가 있는데
for문을 사용해서 복사해보자
let user = {
name:"John",
age:23,
sizes:{
height:180,
weight:72
}
}
function copyObj(Obj){
let result = {};
for(let key in obj){
if(typeof obj[key] ==="obj") result[key] = copyObj(obj[key]);
else result[key] = obj[key];
}
return result;
}
admin.name = "Park"
user.age = 30;
console.log(admin.name) //Park
console.log(user.name) // John
console.log(admin.age) //23
console.log(user.age) //30
이거 좀 복잡하다.
더 쉽고 빠른 복사가 있다
JSON 객체를 이용한 깊은 복사.
let user = {
name:"John",
age:23,
sizes:{
height:180,
weight:72
}
}
let admin = JSON.parse(JSON.stringify(user));
admin.name = "Park"
user.age = 30;
console.log(admin.name) //Park
console.log(user.name) // John
console.log(admin.age) //23
console.log(user.age) //30
stringify를 통해 문자열로 바꿔주고 다시 JSON 객체로 parse하여 admin에 복사를 해준다.