
자바스크립트의 기본을 공부하기로 마음을 먹은건 코테를 보고나서다.
2차코테 과제로 기능을 구현하는게 있었는데
네개의 기능중 하나밖에 구현하지 못했었다.
이 참담한 나의 실력에 반성을 하며 오늘 블로그를 만들고
앞으로 매일 공부한 내용을 이 블로그에 써볼까 한다.
이전에는 전혀 신경을 쓰지 않아 놓친 부분이다.
자바스크립트에는 2개의 기본타입이 있다. primitive type 과 reference type 이다.
이름에 그 뜻이 그대로 나와있는데, 원시타입과 레퍼렌스 타입이다.
원시타입:
NumberStringBooleannullundifinedSymbol
참조타입:ArrayFunctionDateRegExpMapWeakMapSetWeakSet
여기서 Symbol, WeakMap, WeakSet은 잘 모르는 타입인데 이것도 공부해야겠다.
변수를 선언하면 메모리에 저장된다.
근데 원시타입과 참조타입이 그냥 바로 저장되는게 아니다.
그냥 a=1 이런식으로 뙇 저장되는게 아니라
아래와같은 순서를 따른다
const a = 1;
- 스택메모리에서 @1001 메모리를 확보한다
- 해당 공간의 식별자를 a로 지정한다.
- 스택메모리의 빈 공간에 1을 저장한다.(임의로 @2001이라 지정하겠따.)
- 스택메모리에서 a라는 식별자를 검사한다.
- @1001의 값에 @2001을 지정한다.
생각보다 단계가 많다.
자바스크립트의 변수 타입이 자유로운 이유가 여기에서 나온다.
그리고 동시에 메모리도 더욱 효율적으로 관리할 수 있다고 한다.
만약 여기서 a를 찾는다면
아래와 같은 과정을 거치게 된다.
- 식별자 a를 찾는다.(@1001이 발견된다.)
- 값이 @2001을 가리키므로 해당 주소로 이동한다.
- 1를 반환한다.
원시타입 데이터는 모두 불변값이다.
let a = 1;
a = 2;
이렇게 값이 잘 바뀌는데 왜 불변값이지?
이유는 간단하다. 한 번 데이터 할당이 이뤄진 공간은 재할당이 불가능하다.
그래서 원시 테이터는 불변값이라고 한다.
원시 데이터가 불변값이면 참조타입은 어떨까?
참조타입의 값을 할당하는 과정을 보면 알 수 있을것같다.
const objectT = {
num: 1,
nam: 2,
}
- 스택메모리에서 빈 공간을 확보(@1002), 식별자 이름은 objectT로 지정한다.
- 메모리 빈 공간을 확보(@3001), 참조타입이므로 별도공간 확보(@5001~?), @3001에 저장
- @5001, @5002에 식별자 num, nam 저장
- 메모리에서 1 검색, 없으므로 @3002에 저장, 해당주소를 @5001에 저장
- 메모리에서 2 검색, 없으므로 @3003에 저장, 해당주소를 @5002에 저장
현재 상황을 나타내면 이렇다.
@1002 {objectT : @3001 }
@3001 {@5001 ~ ?}
@3002 {1}
@3003 {2}
@5001 {num : @3002}
@5002 {nam : @3003}
원시 데이터와는 다르게 객체의 공간이 따로 존재하는걸 알 수 있다.
그리고 두 타입은 모두 불변값이라 할 수 있다.
식별자에 값을 재할당 하면 메모리에 저장된 값이 바뀌는게 아니라
다른 메모리에 값을 할당 후 해당 주소의 값을 갖고 있기 때문이다.
얕은복사는 객체의 바로 아래단계의 갚만 복사하는 방법이다.
즉, 참조형 데이터의 값을 복사할 때 주소값만 복사한다는 의미이다.
const obj = {
name: 'Song',
hobby: {
first: 'coding',
second: 'running',
}
};
const obj2 = {...obj};
console.log( obj === obj2 );//false
obj2.name = 'Min';
console.log( obj.name === obj2.name); //false
obj2.hobby.first = 'working';
console.log( obj.hobby.first === obj2.hobby.first); //true
얕은복사를 했기 때문에 obj, obj2의 비교를 하면 false가 나온다.
obj2.name을 바꿨을 때도 다른 값이라고 나온다.
하지만 hobby안의 first는 바꿔도 같은값이라고 나오는 이유는 뭘까? 답은 간단하다.
name, hobby 의 주소가 복사 됐는데, hobby 안의 first, second의 주소는 복사되지 않았기 때문이다.
위의 문제를 해결하기 위해 first, second의 주소도 복사하는 방법이다.
그러기 위해선 재귀적으로 모든 내부 값들을 순회해서 값들을 복사 해줘야 한다.
const deepCopy = function(target) {
const result = {};
// target이 null인지 체크하는 이유는 null도 오브젝트이기 떄문이다.
if (typeof target === 'object' && target !== null) {
for (const prop in target) {
result[prop] = deepCopy(target[prop]);
}
}else {
result = target;
}
return result;
}
혹은 JSON을 이용한 방법이 있는데 이 방법은 재귀함수보다 느린 방법이다.