원시타입과 객체타입에 대해서 제대로 알고 넘어가기 위해 오늘은 원시타입과 객체타입, 그리고 더 나아가 얕은복사, 깊은복사에 대해서도 알아보자.
원시타입과 객체타입
원시타입
1. 원시타입의 값
원시타입의 값은 변경 불가능한 값이다. 읽기전용이다.
1 | var str = "hello"; |
변수 str의 첫번째 문자열을 인덱스로 접근하여 직접 바꾸려했지만 변경불가능하여 바꿀 수 없다.
2. 원시타입의 메모리 공간
원시타입은 변수 할당 시 메모리 공간에 실제 값을 저장한다.
변수와 메모리에 대해 자세히 언급하면 사실 변수라는 식별자가 값을 저장하는 게 아닌 값이 저장된 메모리 공간에 대한 메모리 주소를 저장하고 있다.
즉, 메모리 공간에는 값이 저장되어 있고 변수라는 식별자는 메모리 공간의 메모리 주소를 저장한다.
3. 원시타입 값의 전달
원시값을 갖는 변수를 다른 변수에 할당하면 원시값이 복사되어 전달된다.
1 | var str = "hello"; |
사실 값이 복사되어 전달되는 것이 아니고 동일한 값을 새로운 메모리 저장공간에 저장한 뒤 해당 메모리 공간의 메모리 주소를 copy라는 변수에 할당하는 것이다.
객체타입
1. 객체타입의 값
객체타입의 값은 변경가능한 값이다.
1 | var obj = { |
2. 객체타입의 메모리 공간
객체타입은 변수 할당 시 메모리 공간에 참조값(주소값)이 저장된다.
원시타입에서는 메모리 공간에 값이 저장되고 변수 식별자에 해당 메모리 공간을 가리키는 주소가 저장되어 있다.
하지만, 객체타입에서는 메모리 공간에 다른 메모리 공간을 가리키는 메모리 주소가 담겨있다. 다시말해서, 객체타입의 메모리는 원시타입의 메모리보다 과정이 한번 더 일어나게 되는 것이다.
3. 객체타입 값의 전달
객체를 가리키는 변수를 다른 변수에 할당하면 원본의 참조값(주소값)이 복사되어 전달된다.
1 | var person = { |
변수 person과 copy는 {name:’Lee’} 객체 프로퍼티들의 주소가 담겨있는 메모리 공간의 메모리 주소를 저장한다. 그러므로 같은 참조값(주소값)을 비교하고 있기 때문에 일치 비교 연산자가 true가 나왔다.
객체타입의 얕은복사
객체를 spread 문법을 사용하여 얕은복사를 해보자.
1 | let person = { |
변수 person의 원시타입의 값을 수정하였을 때, 서로의 원시타입의 값은 공유하지 않는다. 하지만 객체타입의 값을 바꾼 경우 서로의 객체타입의 값을 공유하는 모습을 볼 수 있다.
왜 그럴까? 앞서 언급한 내용으로 깊게 파헤쳐보자.
- person, someone은 일치하지 않으니 서로 다른 주소값을 갖는다. 각각의 주소는
javascript {name:'yiju',fruit:{1:'peach',2:'strawberry'}}
객체 프로퍼티들의 주소를 담고있는 메모리 공간을 가리킨다.
예를 들면 name 식별자가 가리키는 주소, fruit 식별자가 가리키는 주소 이런식으로 프로퍼티의 주소들을 담고 있다.
여기서 name 식별자는 원시타입의 값을 가리키는 메모리 주소를 저장한다. javascript person.name = 'minseok'
을 실행하면 person.name과 someone.name이 서로 다른 주소값을 갖게된다.
- fruit의 식별자 주소는
javascript {1:'peach',2:'strawberry'}
프로퍼티들의 주소를 담고있는 메모리 공간을 가리킨다. person.fruit와 someone.fruit가 서로 같다(메모리 주소가 같다). 즉, fruit 프로퍼티들의 주소가 담긴 메모리 공간을 가리키는 메모리 주소가 같다.
그리하여 javascript fruit['1'] = 'watermelon'
로 fruit 프로퍼티인 1을 수정하면 식별자인 1이 가리키는 메모리 주소가 바뀌게 되고 person과 someone 식별자가 식별자 1을 포함하는 프로퍼티들의 주소를 담은 메모리 공간을 가리키는 메모리 주소는 변하지 않으므로 서로 공유하게 된다.
객체타입의 깊은복사
객체타입의 깊은복사는 JSON.parse, JSON.stringify 메서드를 사용하여 구현할 수도 있고 lodash 라는 라이브러리를 사용한다.
하지만 JSON.stringify 방식으로는 함수(메서드)를 복사할 수 없기 때문에 재귀를 사용하거나 실무에선 라이브러리를 사용한다.
lodash 방법
1 | const o = { x: { y: 1 } }; |
JSON 방법
1 | const a = { |
소감
자바스크립트 DeepDive 책을 읽으면서 팀원들과 각자 공부한 내용을 말로 풀어서 설명하다보니 내가 무엇이 부족한지 알 수 있었고 내가 모르거나 제대로 알지 못하던 부분을 확실히 알고 이렇게 TIL까지 작성하면서 정리하니 기억에 오래 남을 것 같다.