코어 자바스크립트를 읽고 공부한 부분을 정리해보고자 한다.
기본형
은 할당이나 연산시 복제되고 참조형
은 참조된다.🧐 둘 모두 복제를 하지만 다른 점이 있다. 기본형의 경우, 값이 담긴 주솟값을 바로 복제하지만 참조형의 경우, 값이 담긴 주솟값들로 이루어진 묶음을 가리키는 주솟값을 복제한다는 점이 다르다.
기본형은 주솟값을 복사하는 과정이 한번만 이뤄지고 참조형은 한 단계를 더 거치게 된다.
기본형은 불변성
을 띈다. 이 불변성을 이해하기 위해서는 메모리와 데이터에 대한 지식이 필요하다! 메모리와 데이터에 대해 한번 살펴보자.
컴퓨터는 모든 데이터를 0 또는 1로 바꿔 기억한다. 0 또는 1만 표현할 수 있는 하나의 메모리 조각을 비트
라고 한다.
메모리는 매우 많은 비트들로 구성되어있고 각 비트는 고유한 식별자
를 통해 위치를 확인할 수 있다.
많은 비트를 한 단위로 묶으면 검색 시간도 줄일 수 있고 표현가능한 데이터 개수도 늘어난다. 이렇게 바이트
라는 단위가 생겼다. 1바이트는 8개의 비트로 구성되어 있다.
자바스크립트는 상대적으로 메모리 관리에 대한 압박에서 자유로워졌기에 메모리 공간을 좀 더 넉넉하게 할당했다.64비트 즉 8바이트를 확보한다.
⭐️ 모든 데이터는 바이트 단위의 식별자, 더 정확하게는 메모리 주솟값을 통해 서로 구분하고 연결할 수 있다.
🧐자바스크립트의 메모리 관리에 대해 한번 알아보자!
=> 자바스크립트는 객체가 생성되었을 때 자동으로 메모리를 할당하고 쓸모가 없어지면 자동으로 해제한다(가비지컬렉션:자동메모리 관리방법)
메모리 생존주기를 살펴보면 1. 필요할 때 할당 2.사용한다(읽기,쓰기) 3.필요없어지면 해제
변수명
메모리에 값을 저장하기 위해서는 먼저 메모리에 확보해야 할 메모리의 크기를 알아야 한다. 값의 종류(데이터 타입)에 따라 확보해야할 메모리 크기가 다르기 때문이다.
기본형 데이터가 모두 불변값이라면 참조형 데이터는 모두 가변값일 것 같다. 그러나, 기본적인 성질은 가변값인 경우가 많지만 설정에 따라 변경 불가능하기도 하다.
📍 기본형과 참조형 데이터의 가장 큰 차이점
기본형은 값을 복사하고 참조형은 주솟값을 복사한다. 그러나 어떤 데이터 타입이든 변수에 할당하기 위해서는 주솟값을 복사해야 한다.
엄밀히 따지면 자바스크립트의 모든 데이터 타입은 참조형 데이터
일 수밖에 없다. 다만 기본형은 주솟값을 복사하는 과정이 한 번만 이뤄지고 참조형은 한 단계를 더 거치게 된다.
ex) let a=1
// a는 그냥 a 입력하면 접근이 가능하다.
let b=[1,2,3]
//b는 data에 접근하려면 index로 한번 더 들어가서 접근해야 값을 얻을 수 있다(2번이상 접근해야함)
참조형 데이터의 가변
은 데이터 자체가 아닌 내부 프로퍼티를 변경할 때만 성립한다. 데이터 자체를 변경하고자 하면(새로운 데이터를 할당하고자 하면) 기본형 데이터와 마찬가지로 기존 데이터는 변하지 않는다!
어떤 상황에서 불변 객체가 필요할까? 값으로 전달받은 객체에 변경을 가하더라도 원본 객체는 변하지 않아야 하는 경우가 있다. 이때 불변객체가 필요하다.
🧐 자바스크립트에서 객체를 복사하는 방법?
얕은 복사는 바로 아래단계의 값만 복사하는 방법
- 객체가 담겨있는 변수를 다른 변수에 할당하면 데이터 복사가 아닌 참조가 일어나게 되어 한 변수의 데이터를 변경하면 다른 변수의 데이터도 함께 변경이 된다.(즉,사본을 만들어내지 않고 원본을 참조하도록 복사한척 하는 것)
const person1={name:'chloe'}; const person2=person1; person1.name='jung'; person2.name//jung person1===person2;
데이터가 그대로 하나 더 생성된 것이 아닌 해당 데이터의 메모리 주소를 전달하게 돼서 결국 한 데이터를 공유하게 되는 것이다.
깊은 복사는 내부의 모든 값들을 하나하나 찾아서 전부 복사하는 방법
- 얕은 복사처럼 한 데이터의 공유가 아닌 똑같은 구조의 객체를 하나 더 생성하여 따로 사용하고자 할 때 깊은 복사 개념을 사용한다. (완벽하게 원본과 사본을 나눠 복사하는 방법)
const person1={name:"chloe"}; const person2=Object.assign({},person1); person1.name="jung"; person2.name// chloe 전혀 다른 메모리 주소의 데이터이므로 person2의 값은 변하지 않는다. person1!==person2 형태만 같고 각자 다른 메모리 주소에 저장되어 있는 데이터이다.
데이터 참조가 아니라 객체의 형태를 그대로 복사하게 함으로써 한 객체가 변경되어도 다른 객체의 데이터에는 영향이 없다!
Object.assign()
Object 형태의 데이터를 쉽게 병합할 수 있게 해주는 함수
const originObj={a:1};
const newObj=Object.assign({},originObj)
// 빈 object에 originObj를 병합하여 반환
newObj//{a:1}
originObj ===newObj //false
빈 object에 복사를 하려는 Object를 병합한다. 그러면 형태는 originObj이지만 실제로는 빈 Object와 originObj가 병합된 새로운 Object가 반환된다. (형태는 같지만 새로운 객체가 반환된다)
전개 연산자(Spread Operator)
const obj1={a:1,b:2};
const obj2={c:3};
const obj3={...obj1,...obj2};
obj3//{a:1,b:2,c:3}
...을 이용하여 배열이나 object형태의 괄호를 이용해 풀어서 사용하는 방식이다.
전개 연산자를 이용한 깊은 복사는 아래와 같은 방법으로 할 수 있다.
const obj1={a:1,b:2}
const obj2={...obj1};
obj2//{a:1,b:2}
obj1===obj2//false
그러나!! 이러한 깊은 복사는 현재의 Depth이상으로는 깊은 복사를 하지 않는다.
const obj1={a:{b:1}};
const obj2={...obj1};
obj2//{a:{b:1}}
obj1 === obj2// false
Depth가 2인 Object를 전개 연산자를 이용해 Obj2 변수에 할당했다.
obj1과 obj2는 형태가 같지만 연산자를 이용해 확인해보면 각자 다른 메모리 주소에 저장된 데이터로 제대로 깊은 복사가 된 것처럼 보인다.
그러나.. 깊은 복사가 된 것은 제일 바깥의 Depth뿐이다..
const obj1={a:{b:1}};
const obj2={...obj1};
obj2//{a:{b:1}}
obj1===obj2//false
obj1.a===obj2.a//true????
두번째 Depth이상의 요소들은 참조 값을 전달하는 얕은 복사를 하게 되는 것이다ㅠㅠ
🧐완벽하게 깊은 복사를 하는 방법에는 무엇이 있을까?
1) 재귀적으로 깊은 복사를 수행한다!
--> 그러나 깊은 복사를 하려는 형태에 맞게 재귀 함수를 만들어서 복사를 해야 한다. 매우 귀찮은 일..
2)JSON.parse()와 JSON.stringify()함수 사용
-->JSON.stringify함수를 이용해서 Object전체를 문자열로 변환 후, 다시 JSON.parse함수를 이용해서 문자열을 Object형태로 변환한다.
👉 깊은 함수,얕은 함수 부분 참고: https://helloinyong.tistory.com/267
undefined:
1) 사용자가 명시적으로 지정하는 경우
2) 값이 존재하지 않을 때 자바스크립트 엔진이 자동으로 부여하는 경우
=>이 경우는 해당 프로퍼티 내지 배열의 키값(인덱스)자체가 존재하지 않는다. (값이 없음)null
비어있음을 명시적으로 나타내고 싶을 때는 undefined가 아닌 null을 쓰면 된다.