코드잇 스프린트 4기
4주 차 위클리 페이퍼
데이터 타입
자바스크립트에서 데이터 타입은 크게 기본형 타입, 참조형 타입이 있다.
기본형 타입은 값의 주소를 참조한다.
참조형 타입은 값의 주솟값들로 이루어진 묶음을 가리키는 주소를 참조한다.
기본형 타입의 예를 보면
1 let a = 'codeit';
2 let b = a;
3 a = 'codeit sprint';
4 console.log(a); // 'codeit sprint'
5 console.log(b); // 'codeit'
1 라인은 'codeit'
이라는 데이터를 메모리 공간에 확보하고 그 메모리 공간의 주소를 식별자 a
가 저장된 메모리 공간에 저장한다.
2 라인은 식별자 a
가 저장하고 있는 'codeit'
의 메모리 주소를 복사한다.
결국 둘은 같은 데이터가 저장된 메모리 공간을 바라보게 된다.
3 라인은 a
에 'codeit sprint'
를 재할당 하게 되는데 이때 메모리 공간에 저장된 'codeit'
을 'codeit sprint'
로 변경하는 것이 아닌 새로운 메모리 공간을 확보해 'codeit sprint'
를 저장하고 그 주소를 식별자 a
에 저장하게 된다.
결국 a
는 'codeit sprint'
가 저장된 주소를 저장하고 b
는 'codeit'
이 저장된 주소를 저장하게 되어 console.log
를 출력하면 서로 다른 결과가 나온다.
위와 같이 기본형 타입은 값을 재할당할 때 메모리 공간을 새로 확보해 저장하고 이러한 현상을 불변(immutable)하다고 한다.
참조형 타입의 예를 보면
1 let a = {
2 name: 'codeit',
3 age: '29',
4 }
5 let b = a;
6 a.name = 'codeit sprint';
7 console.log(a.name); // 'codeit sprint'
8 console.log(b.name); // 'codeit sprint'
1 ~ 4 라인은 데이터를 저장할 메모리 공간을 확보하고 그 메모리 공간의 주소를 식별자 a
가 저장된 메모리 공간에 저장한다. 그런데 데이터가 데이터의 집합(객체)로 이루어져 별도로 객체의 프로퍼티 식별자(name
, age
)들이 저장될 공간을 마련하고 그 주소들을 저장한다. 그리고 각 식별자들의 값('codeit'
, 29
)을 메모리 공간에 저장하고 그 주소를 각 프로퍼티 식별자가 저장된 메모리에 저장한다.
5 라인은 a
가 저장하고 있는 주소를 복사한다. 그리고 그 주소는 프로퍼티 식별자(name
, age
)가 저장된 주소들의 묶음이다.
6 라인은 a.name
에 'codeit sprint'
를 재할당 하게 되는데 메모리 공간을 새로 확보해 저장 후 그 주소를 a.name
에 저장한다. 즉, a
가 저장하고 있는 주소는 변경사항이 없이 a
의 값을 변경할 수 있는데 이러한 현상을 가변(mutable)하다고 한다.
결국 a
와 b
는 여전히 같은 주소를 저장하고 있고 console.log
를 출력하면 서로 같은 결과가 나오게 된다.
복사
참조형 타입을 기본형 타입을 복사할 때처럼 복사하면 주소값만 복사해서 프로퍼티가 변화하면 서로 영향이 끼친다는 건 알게 되었다.
참조형 타입의 가변은 어디까지나 내부 프로퍼티를 변경할 때 이루어지고 데이터 자체를 변경하게 되면 불변을 띈다.
데이터를 변경(새로운 객체 생성)의 예를 보면
1 function copyObj(oldObj) {
2 const newObj = {};
3 for (const key in oldObj) {
4 newObj[key] = oldObj[key];
5 }
6 return newObj;
7 };
8 let a = {
9 name: 'codeit',
10 age: '29',
11 team: {
12 color: 'pupple',
13 code: 'fighting'
14 }
15 };
16 let b = copyObj(a);
17 a.name = 'codeit sprint';
18 console.log(a.name); // 'codeit sprint'
19 console.log(b.name); // 'codeit'
20 a.team.code = 'happy';
21 console.log(a.team.code); // 'happy'
22 console.log(b.team.code); // 'happy'
16 라인에서 b
는 copyObj
함수를 통해 새로운 객체를 만들어주어 a
와 독립적인 객체를 만들어주었다.
17 ~ 19 라인을 보면 a.name
의 값을 변경해도 b.name
에는 영향이 끼치지 않은 것이 보인다.
하지만 이번 예제에선 객체 a
의 프로퍼티에 객체 team
이 들어있는 중첩 객체 형태이다.team
역시 참조형 타입이기 때문에 copyObj
함수를 통해서는 team
의 주소가 복사되었다.
20 ~ 22 라인을 보면 a.team.code
의 값을 변경했을 때 b.team.code
의 값이 변경됨을 확인할 수 있다.
위와 같이 바로 아래 단계의 값만 복사하는 방식을 얕은 복사(shallow copy)라고 한다.
얕은 복사의 copyObj
함수를 조금 변형하여 중첩 객체의 형태에도 제대로 된 복사가 되는 예를 보면
1 function copyObj(oldObj) {
2 let newObj = {};
3 if (typeof oldObj === 'object' && oldObj !== null) {
4 for (const key in oldObj) {
5 newObj[key] = copyObj(oldObj[key]);
6 }
7 } else {
8 newObj = oldObj;
9 }
10 return newObj;
11 };
12 let a = {
13 name: 'codeit',
14 age: '29',
15 team: {
16 color: 'pupple',
17 code: 'fighting'
18 }
19 };
20 let b = copyObj(a);
21 a.team.code = 'happy';
22 console.log(a.team.code); // 'happy'
23 console.log(b.team.code); // 'fighting'
3 라인에서 typeof null
의 값은 object
이기 때문에 별도로 oldObj !== null
를 처리하였다.
내부 프로퍼티가 참조형 타입일 경우 재귀를 통해 그 내부까지 완전 복사를 진행하였다.
이렇게 중첩 객체를 복사할 때 완전 독립된 새로운 복사본을 만드는 것을 깊은 복사(deep copy)라고 한다.
감사합니다.
'코드잇 스프린트 4기 > 위클리 페이퍼' 카테고리의 다른 글
[JavaScript] 이벤트 버블링, 캡처링, 위임 (0) | 2024.01.27 |
---|---|
[JavaScript] var, let, const (0) | 2024.01.20 |
[Git] Git-flow (0) | 2024.01.12 |
[Git] 머지(merge) (0) | 2024.01.12 |
[CSS] 포지션(Position) (0) | 2024.01.07 |
댓글