1. 데이터타입의 종류
- 기본형과 참조형 구분하는 기준
- 복제의 방식
- 기본형 : 값이 담긴 주소값을 바로 복제
- 참조형 : 값이 담긴 주소값들로 이루어진 묶음을 가리키는 주소값을 복제
- 불변의 여부
2. 데이터 타입을 이해하기 위해 필요한 배경지식
- 메모리, 데이터
- bit : 0과 1을 가지고 있는 작은 메모리 조각
- bit 가 늘어날 때는 2의 배수로 늘어난다.
- memory : bit 가 모여서 메모리가 된다.
- byte : 너무 적고 많은 bit를 저장하면 비효율적이기 때문에 8개로 묶어서 저장한다.
💡 모든 데이터는 byte 단위의 식별자인 메모리 주소값을 통해서 서로 구분이 된다.
3. 변수 선언과 데이터 할당
-
변수를 선언하고 데이터를 할당할 때 과정
- 변수 영역과 데이터 영역으로 나뉜다.
- 변수 영역에는 식별자를 저장하고 데이터 영역에는 데이터를 저장한다.
- 변수 영역에서 값으로 데이터 영역에 저장된 알맞은 주소를 가져온다.
-
값을 바로 변수에 대입하지 않는 이유
- 자유로운 데이터 변환 : 숫자는 상관없지만 문자열은 데이터의 길이가 길어질 수도 있기 때문에 변수 영역에 값을 저장하면 뒤에 있는 나머지 값들이 뒤로 밀리게 되서 굉장히 비효율적이게 된다.
- 메모리의 효율적인 관리 : 똑같은 데이터를 한번만 저장해서 알맞은 주소를 가져오면 된다.
4. 기본형 데이터와 참조형 데이터
- 불변값과 불변성
- 데이터 영역의 메모리가 바뀌는 것이 아니라 새로운 데이터 영역에 새로운 데이터를 저장하고 변수 영역에서 주소값을 바꿔주는 것이다.
- 가비지컬렉팅
- 쓰레기를 모으는 것
- 데이터 영역에서 사용되고 있다가 변수 영역의 값이 바뀜으로써 더이상 사용되지 않는 데이터 영역을 수거함, 수거된 공간은 빈 공간이 된다.
💡 변수 영역의 값이 바뀐다는 것은 데이터 영역의 주소가 바뀌는 것을 의미한다.
-
변수, 상수를 결정하는 요소
- 변수 영역에 있는 주소 값이 바뀔 수 있느냐를 묻는게 아닌 데이터 영역에 있는 값이 변경될 수 있는지를 묻는다.
- 변수는 바꿀 수 있는 값 :
let, var
- 상수는 바꿀 수 없는 값 :
const
-
예시
- 1 : b 의 값이 처음에는 5이기 때문에 데이터 영역 주소값 5003을 불러온다.
- 2 : b 의 값이 5에서 7로 바뀌기 때문에 데이터 영역 주소값 5004를 불러온다.
- 즉 b 는 변수이고, 데이터 영역에서 값이 바뀐게 아니므로 불변성이다.
-
가변값과 가변성
- 참조형 데이터의 변수 할당 과정 (1)
- 오브젝트의 데이터
{ 부터 } 까지
를 저장하기 위해서는 데이터 영역에서 한 공간에만 저장할 수 없다.
- 따라서 객체의 변수 영역 즉, 프로퍼티 영역(obj1을 위한 별도 공간)에서 식별자 a, b를 저장한다.
- 데이터 영역에 1, "bbb"를 저장해서 프로퍼티 영역에 값으로 데이터 주소를 가져온 뒤 프로퍼티 영역의 주소를 데이터 영역의 값으로 가져온다.
- 데이터 영역의 주소를 변수 영역의 값에 주면 완료!
-
참조형 데이터의 변수 할당 과정 (2)
- 오브젝트 안에
arr
있으므로 arr
을 위한 영역도 있어야 한다.
arr
영역에 데이터 주소를 값으로 넣어주고 데이터 영역에 arr 영역의 주소를 저장한다.
- 프로퍼티 영역에서
arr
의 값으로 데이터 영역의 주소를 준다.
- 나머지는 위의 내용과 똑같다.
💡 기본형 데이터와 참조형 데이터의 차이점은 객체의 변수 영역의 별도 존재 여부이다.
- 참조형 데이터가 가변한다고 하는 이유
- 참조형 데이터의 변환은 데이터 영역의 빈 주소에 새로운 값을 저장하고 프로퍼티 영역의 값이 새로운 데이터 값의 주소로 바뀌는 것이다.
- 변수 영역의 값이 바뀌는 것이 아니라 프로퍼티 영역의 값이 바뀌는 것이기 때문에 가변성을 띈다고 볼 수 있다.
5. 변수 복사
let a = 10;
let b = a;
b = 15;
let obj1 = { c: 10, d: "ddd" }
let obj2 = obj1
obj2.c = 20
- 예시
- case 1
- case 2
obj1 === obj2
이다.
- 이유 : 변수 영역에서의 값이 같은 주소를 할당하고 있기 때문이다.
프로퍼티 영역의 값이 주소 5001 에서 5004 로 변했기 때문에 obj1.c의 값도 20이 된다.
- 문제 : obj2만 바꾸고 싶은데 obj1도 바뀌었다.
- 답안 : 가변임을 유의해야 하고, 불변하도록 만들어야 한다.
불변 객체
let obj1 = { c: 10, d: "ddd" }
let obj2 = obj1
obj2.c = 20
- 예시 (가변 객체)
- 문제 : obj2만 바꾸고 싶은데 obj1도 바뀌었다.
- 답안 : 가변임을 유의해야 하고, 불변하도록 만들어야 한다.
let obj1 = { c: 10, d: "ddd" }
let obj2 = { c: 20, d: "ddd" }
obj2.c = 30
-
예시 (불변 객체)
- obj2 = obj1 이 아닌 obj2 = { c: 20, d: "ddd" } 로 할당한다.
- 프로퍼티 영역에서 바라보는 주소가 다르기 때문에 값을 바꾸어도 obj1 에게 영향이 없다.
-
불변 객체의 필요성
- 예시 1 (가변 객체)
- input : user의 형식을 가지고 있는 객체, 바꿀 이름
- output : 이름 바꿔서 복사한 그 객체
- 예시 2 (비효율적인 코드)
- 불변하게 하려면 새로운 객체를 return 해줘야한다.
- 문제 : 프로퍼티가 2,3개 일때는 가능하지만 많은 수의 프로퍼티를 가졌을 때는 비효율적이라 쓰지 않는다.
for in(index를 가져온다) 을 활용한 코드
for 문을 돌면서 새로운 값을 넣어준다.
depth (1) = string, number 등 한개의 값
depth (여러개) = 객체(배열,함수 등)
depth가 여러개 일 때 값을 새롭게 생성을 못한다( for 문을 한번만 돌기 때문에 )
undefined & null
let arr 1 = [];
arr1.length = 3;
console.log(arr1)
let arr2 = new Array(3)
console.log(arr2)
let arr3 = [undefined, undefined, undefined]
console.log(arr3)
- undefinded
- 사용자 지정
- 자바스크립트 엔진에서 자동 부여
- 변수에 값이 지정되지 않은 경우, 데이터 영역의 메모리 주소를 지정하지 않은 식별자에 접근할 때
- 이나 []로 접근하려 할 때, 해당 데이터가 존재하지 않는 경우
- return 문이 없거나 호출되지 않는 함수의 실행 결과
- 비어있는 요소와
undefined
는 다르다.
forEach, map, filter, reduce
를 실행할 경우
- empty(길이는 지정했지만 값이 없는 경우) > skip
- undefined > 수행한다.
- null
- '없다' 를 명시적으로 표현할 때 사용한다.
typeop null
은 오브젝트 타입이기 때문에 if문을 쓸때 주의해야 한다.
🧐 좋은 개발자란 ? 효율화를 고려하여 코드를 짜야한다. ( 반복적인 부분을 줄여야 한다 > 유지보수하기 편하다. )