[코어자바스크립트] - 1장. 데이터타입

sypaik-dev·2023년 4월 7일
0
post-thumbnail

이 글은 코어자바스크립트 1장을 읽고 정리한 글입니다.

01. 데이터 타입의 종류와 배경지식

데이터 타입
데이터 타입은 크게 기본형과 참조형으로 나누어져 있다.
기본형과 참조형 모두 복제
-> 기본형은 값이 담긴 주솟값을 바로 복제
-> 참조형은 값이 담긴 주솟값들로 이루어진 묶음을 가리키는 주솟값을 복제

  • Primitive type (기본형/원시형) - Number, String, Boolean, null, undefined, Symbol
  • Preference type (참조형) - Array, Function, Date, RegExp, Map / WeakMap, Set / WeakSet

메모리와 데이터
컴퓨터는 모든 데이터를 0 또는 1로 표현
비트 - 0 또는 1로 표현할 수 있는 하나의 메모리 조각
메모리는 수많은 비트들로 구성되어 있는데 각 비트는 고유한 식별자를 통해 위치를 확인할 수 있다.
수많은 비트들을 몇 개씩 묶어 하나의 단위로 나타내면 표현할 수 있는 값도 늘어나고 동시에 검색 시간을 줄일 수 있다.
바이트 - 8개의 비트로 구성 (총 2^8, 256개)
자바, C/C++과 같은 정적 타입 언어는 메모리 낭비를 최소화하기 위해 데이터 타입별로 메모리 영역이 정해져 있어 형변환이 필요했지만 자바스크립트는 메모리 관리가 자유로워 형변환이 크게 필요없다.

식별자와 변수
변수는 변경 가능한 데이터가 담길 수 있는 공간 또는 그릇
식별자는 데이터를 식별하는 데 사용하는 이름, 즉 변수명

02. 변수 선언과 데이터 할당

변수 선언

var a;

<변수 선언에 대한 메모리 영역의 변화>

컴퓨터는 메모리에서 비어있는 공간 하나를 확보한다. (1003번)
이 공간에 이름(식별자)를 a로 지정한다.

데이터 할당

var a;			// 변수 a 선언
a = 'abc';  	// 변수 a에 대한 데이터 할당

var a = 'abc' 	// 변수 선언과 동시에 데이터 할당

<데이터 할당에 대한 메모리 영역의 변화>

  • 변수 영역에서 빈 공간을 확보한다. (1003번)
  • 확보한 공간에 이름(식별자)를 a로 지정한다.
  • 데이터 영역의 빈 공간(5004번)에 문자열 'abc'를 저장한다.
  • 변수 영역에서 a라는 식별자를 검색한다.
  • 문자열의 주소 (5004번)을 변수 영역 공간(1003번)에 대입한다.

다시 말해, 변수 영역에 저장된 주소에 데이터를 할당하지 않는다!

💡 왜 데이터를 변수 영역에 직접 대입하고 않고 데이터 영역에 따로 저장하는가?

  • 데이터 변환을 자유롭게 할 수 있고 메모리를 효율적으로 관리하기 위함
  • 만약 직접 대입하면, 데이터 변환 시 확보된 공간을 늘리는 작업이 필요하다.
  • 여유 공간이 없다면 데이터를 전부 옮기고 이동시킨 주소를 각 식별자에 다시 연결하는 등 처리해야할 연산량이 너무 많아진다.
    🗸 따라서 변수와 데이터를 각각의 공간으로 저장하는 것이 데이터의 변환을 처리할 때, 최적이다!

데이터 변환

var a = 'abc'
a = 'abcdef';

<문자열 변환에 대한 메모리 영역의 변화>

  • 데이터 영역의 빈 공간(5005번)에 문자열 'abcdef'를 저장한다.
  • 변수 a의 메모리를 찾고 해당 메모리 값을 5005로 교체한다

03. 기본형 데이터와 참조형 데이터

불변값

  • 변수와 상수를 구분 짓는 요소 - 변수 영역 메모리의 변경 가능성
  • 불변성 여부를 구분 짓는 요소 - 데이터 영역 메모리의 변경 가능성
  • 기본형 데이터 - Number, String, Boolean, null, undefined, Symbol ==> 불변값
var a = 'abc';
a = a + 'def';

var b = 5;
var c = 5;
b = 7;

문자열 값도 숫자도 다른 값으로 변경할 수 없다. 여기서 변경은 새로 만드는 동작을 통해서만 이루어진다.

가변값

var obj1 = {
	a: 1,
  	b: 'bbb'
};

  • 빈 공간에 obj1을 저장한다.
  • obj1은 여러 개의 프로퍼티로 이루어진 데이터 그룹이다. 내부의 프로퍼티를 저장하기 위해 별도의 변수 영역을 마련하여 영역의 주소인 @7103 ~ ?을 5002에 저장한다.
  • @7103과 @7104는 각각 a와 b라는 프로퍼티 이름을 저장한다.
  • 프로퍼티 a와 b에 해당하는 숫자, 문자열의 메모리 주소 @5004, @5005를 저장한다.

💡 기본형 데이터와의 차이는?
-> 객체의 변수인 프로퍼티 영역이 별도로 존재한다는 점이다!
데이터 영역에 저장된 값은 모두 불변값(숫자, 문자열)이지만 변수에는 다른 값을 얼마든지 대입할 수 있기 때문에 불변하지 않다. (= 가변적이다)

참조형 데이터의 프로퍼티를 재할당하면 어떻게 될까?

var obj1 = {
	a: 1,
  	b: 'bbb'
};

obj1.a = 2;

obj1은 변하지 않고, obj1의 프로퍼티 a가 저장된 주소값만 5004에서 5003으로 교체된다.

참조형 데이터의 프로퍼티에 다시 참조형 데이터를 할당하는 경우를 중첩객체 라고 한다.

var obj = {
	x: 3,
  	arr: [3, 4, 5]
};

새로 추가된 과정은 먼저,

  • @7104에 저장할 값은 배열로 내부 프로퍼티들을 저장하기 위해 별도의 변수 영역을 확보하고 변수 영역의 주소값을 5003에 저장한다.
  • 배열의 길이가 3으로 3개의 변수 공간을 확보하고 각각 인덱스를 부여한다.
  • arr 내부의 프로퍼티의 값을 각각 5002, 5004, 5005에 저장한다.

만약 중첩 객체의 프로퍼티를 재할당한다면 어떻게 될까?

어떤 데이터에 대해 자신의 주소를 참조하는 변수의 개수를 참조 카운트라고 한다.
해당 그림에서 @5003, @8104 ~ 는 참조 카운트가 1이었다가 0이 된다. 참조 카운트가 0인 메모리 주소를 가비지 컬렉터(Garbage Collector, GC)로 수거대상이 된다. 수거 대상이 된 가비지 컬렉터는 런타임 환경에 따라 특정 시점이나 메모리 사용량이 포화 상태에 임박할 때마다 자동으로 수거 대상들을 수거한다. 수거된 메모리는 다시 빈 공간이 되어 새로운 값을 할당받을 수 있다.

변수 복사 비교
<변수 복사>

var a = 10;
var b = a;

var obj1 = {
	c: 10,
  	d: 'ddd'
};
var obj2 = obj1;

앞서 본 과정과 마찬가지로 각각 변수 영역의 빈 공간을 확보하고 a, b를 지정한다. 둘은 각각의 공간을 가지고 같은 주솟값을 갖는다.
그리고 참조형 데이터는 ob1, obj2에 해당하는 각각의 변수 영역의 빈 공간을 확보하고 데이터 영역의 묶음 주소는 같은 주솟값을 갖는다.

<객체의 프로퍼티 변경>

var a = 10;
var b = a;

var obj1 = {
	c: 10,
  	d: 'ddd'
};
var obj2 = obj1;

b = 15;
obj2.c = 20;

반면 다음과 같이 객체의 프로퍼티가를 변경했을 때에는 다르게 동작한다.
기본형 데이터를 복사한 변수는 b는 값이 달라져 서로 다른 주솟값을 가진다. 반면 obj1과 obj2는 프로퍼티가 저장된 메모리의 값만 바뀌어 메무리 주솟값만 변경될 뿐 ojb1과 obj2는 같은 주솟값을 가진다.

<객체 자체를 변경했을 때>

var a = 10;
var b = a;

var obj1 = {
	c: 10,
  	d: 'ddd'
};
var obj2 = obj1;

b = 15;
obj2 = {
	c: 20,
  	d: 'ddd'
}

이와 같이 객체 자체를 변경했을 때에는 객체를 새롭게 만들었기 때문에 obj1 !== obj2가 성립한다.

💡 참조형 데이터의 '가변값'이 언제를 의미할까?
'가변'은 참조형 데이터 자체를 변경했을 때가 아닌 내부의 프로퍼티를 변경했을 때만 성립 가능하다.

04. 불변 객체

참조형 데이터는 '가변적'이라고 하지만 데이터 자체를 변경한다면 기존 데이터는 변경하지 않는 불변성을 확보할 수 있다.
값으로 전달받은 객체에 변경에 변경을 가하더라도 원본 객체는 변하지 않아야 할 때 -> 불변 객체 필요!

얕은 복사

  • 바로 아래 단계의 값만 복사하는 방법
  • 중첩된 객체에서 프로퍼티를 복사할 때 그 주솟값만 복사한다.
    -> 원본과 사본 모두 동일한 참조형 데이터의 주소를 가리킨다.
    -> 사본을 바꾸면 원본도 바뀌고, 원본을 바꾸면 사본도 바뀐다.

깊은 복사

  • 내부의 모든 값들을 하나하나 찾아서 전부 복사하는 방법
  • 객체의 프로퍼티 중 그 값이 기본형 데이터일 경우는 그대로 복사되지만 참조형 데이터는 다시 그 내부의 프로퍼티를 복사해야한다.
    -> 원본과 사본이 서로 완전히 다른 객체를 참조하게 되어 서로 영향을 주지 않는다.

05. undefined와 null

'없음'을 나타내는 값으로 같지만 undefined와 null은 미세하게 다르고 사용하는 목적 또한 다르다.

undefined

  • 사용자가 명시적으로 지정하는 경우
  • 값이 존재하지 않아 자바스크립트 엔진이 자동으로 부여하는 경우
    1. 값을 대입하지 않은 변수
    1. 객체 내부의 존재하지 않는 프로퍼티에 접근하려고 할 때
    2. return 문이 없거나 호출되지 않는 함수의 실행 결과

언제 undefined와 null을 사용할까?

  • 직접 undefined를 할당하지 않고 자바스크립트 엔진이 반환하는 경우에만 할당
  • '비어있음'을 명시적으로 나타내고 싶을 때는 null 사용

typeof null은 object로 어떤 변수의 값이 null인지의 여부를 판별하기 위해 typeof는 적절하지 않다.

var n = null;
console.log(typeof n);		// object

console.log(n == null)		// true
console.log(n === null)		// true

console.log(n == undefined) // true

console.log(n === undefined) // false

null과 undefined를 비교하기 위해서는 동등 연산자(==)로 비교할 경우 true 값을 반환하기 때문에 일치 연산자(===)를 사용하여 판별해야한다.

profile
Frontend Developer

0개의 댓글

관련 채용 정보