원시값 : Number, String, Boolean, undefined, null, Symbol
참조값 : Object(array, function, ...)
원시값의 경우는 값을 복사할 때 복사된 값을 다른 메모리에 할당하기 때문에 원래의 값과 복사된 값이 관계가 없음
const a = 1;
let b = a
b = 2
console.log(a) //1
console.log(b) //2
즉 const a는 a라는 이름으로 집을 만들어주고 1을 집어넣음
let b 는 b라는 집을 만들어주고 a를 집어넣음 이때 a는 const a와 다름
이후 b에게 2를 할당하면
b= 2가 나오게 됨
즉 const a와 let b= a의 a가 서로 다름
하지만 참조값의 경우는 변수가 객체의 주소를 가르킴
const a = {number : 2}
let b = a
b.number = 3
console.log(a) // {number : 3}
console.log(b) // {number : 3}
여기서 const a는 a에게 {number : 2}라고 주소를 지정해줌
let b = a는 b라는 집을 만들어주고 a( {number:2} )라는 주소를 할당해주는 것
그렇게 되면 a의 값이 바뀌게 되면 b도 자동으로 바뀜
이런 특징으로 때문에 복사하는 방법이 두 가지로 나뉨
let a = {
name : '철수',
age : 8,
school : '가나다초등학교'
}
이렇게 있으면
let b = {
name : a.name,
age : a.age,
school : a.school
}
이렇게 복사하면 코드량도 늘고 매우 좋으니 하지 않는게 좋다.
...a
let a = {
name : '철수',
age : 8,
school : '가나다초등학교'
}
let aa = { ...a }
console.log(aa)
{ name: '철수', age: 8, school: '가나다초등학교' }
aa.name = '영희'
console.log(aa)
{ name: '영희', age: 8, school: '가나다초등학교' }
console.log(a)
{ name: '철수', age: 8, school: '가나다초등학교' }
스프레드 연산자를 쓰면 원래 값(a)에 영향을 미치지 않고 수정할 수 있다.
이를 얕은 복사라고 하는데
즉 b라는 주소를 만들고 b의 주소에 a의 값을 채워 넣은거라고 생각하면 됨
그래서 b에 내용을 아무리 수정해도 a가 바뀌지 않게 됨
아래의 경우를 보면 잘 안된다
let a = {
name:"철수",
age:8,
school: "다람쥐초등학교",
hobby: {
hobby1 : "수영",
hobby2 : "게임"
}
let b = { ...a}
b.hobby.hobby1 = '독서'
console.log(b)
{
name:"철수",
age:8,
school: "다람쥐초등학교",
hobby: {
hobby1 : "독서",
hobby2 : "게임"
}
console.log(a)
{
name:"철수",
age:8,
school: "다람쥐초등학교",
hobby: {
hobby1 : "독서",
hobby2 : "게임"
}
이런식으로 a와 b의 hobby1이 모두 바뀌게 된다
왜 그런걸까?
b라는 주소를 만들고 a라는 값을 입력한 건 위의 과정과 동일하나
이때 내부의 hobby는 새로운 주소값을 가지는데 그 주소값을 복사했기 때문에 동일한 주소를 가르키게 된것이다.
즉 참조형 값의 경우 {}, []를 씌우면 무조건 주소(고유값)이 생긴다고 생각하면 편하다.
전체를 객체가 아닌 스트링으로 만들어 버리면?
원시값이기 때문에 그냥 복사가 됨 그것을 다시 객체로 만들어 버리면 새로운 주소(고유값)이 생기게 되는 것이고 원시형을 복사했기 때문에 스트링을 복사하는 시점에서 남남이 되기 때문에 객체로 만들어도 서로 남남임
JSON.stringify()로 객체로 만들고 JSON.parse({})로 새로운 배열로 만들어 버리면 새로운 배열이 하나 튀어나옴
JSON.parse(JSON.stringify())
하지만 이는 매우 느리고 deepth한 데이터에만 사용함
다. lodash 라이브러리를 이용하자