Posts 코어자바스크립트-1.데이터 타입에 대한 정리
Post
Cancel

코어자바스크립트-1.데이터 타입에 대한 정리

코어자바스크립트-1.데이터 타입에 대한 정리 thumbnail

코어 자바스크립트 1주차

1장 데이터 타입

데이터 타입은 크게 기본형, 참조형으로 나눌 수 있다. 기본형은 Number, String, Boolean, null, undefined 등이 있고, 참조형은 Object, Array, Function, Date, RegExp 등이 있다.

보통 기본형은 값을 복사하고, 참조형은 주소를 복사한다고 알고있는데 실제로도 그런지 살펴보자.

메모리와 데이터에 대한 배경지식

컴퓨터에서는 모든 데이터를 메모리 주소를 통해 서로 구분하고 연결할 수 있다.

변수는 변경 가능한 데이터를 담는 공간이다. 보통 이 변수의 이름, 변수명을 식별자라고 한다.

1
var a; // 변수선언

a라는 이름의 변수를 선언하면 컴퓨터는 메모리에서 비어있는 공간을 확보한다. 그리고 이 공간을 a라고 부르자.

이 변수에 실제로 데이터를 할당할 때는 먼저 별도의 메모리 공간을 확보해서 할당할 데이터를 저장한다. 그리고 그 공간의 주소를 a에 저장한다.

1
2
3
4
/* 예제 1 */

var a;
a = 'core javascript';
주소10005000
이름a-
실제 저장된 데이터@5000‘core javascript’

a 라는 공간에 실제 저장된 데이터는 5000(주소)이다.

그런데 만약 a 변수에 값을 재할당하면 어떻게 될까?

1
2
3
4
/* 예제 2 */
var a;
a = 'core javascript';
a = 'javascript study'; // 재할당

5000 주소의 데이터를 변경할 것 같지만, 실제로는 아니다.

주소100050005001
이름a--
실제 저장된 데이터@5001‘core javascript’‘javascript study’

새로운 공간을 만들어 ‘javascript study’라는 문자열을 저장해 두고, 변수 a에는 5001이라는 새로운 주소를 저장한다. 이 때, 5000 주소는 더 이상 참조되지 않기 때문에 나중에 가비지 컬렉터에 의해 지워진다. 그러면 5000 주소는 비어있게 되고, 나중에 새로운 데이터를 저장해야 될 때 5000 주소는 재활용 된다.

가비지 컬렉터는 주기적으로 또는 메모리 사용량에 따라 메모리를 수거해서 빈 공간으로 만들어, 새로운 값을 할당할 수 있도록 만든다. 이 때 메모리 사용량이라 함은 참조 카운트를 말하는데, 어떤 데이터에 대해 자신의 주소를 참조하는 변수의 개수를 참조 카운트라고 한다. 이 참조 카운트가 0이면 메모리를 수거한다.

변수 복사 후 비교

예제 1의 변수 a를 복사해보자. 우선 변수 a의 데이터는 다음과 같이 저장이 되있을 것이다.

주소10005000
이름a-
실제 저장된 데이터@5000‘core javascript’

변수 b에 a를 복사하면 어떻게 될까.

1
2
3
/* 예제 3 */
var a = 'core javascript';
var b = a;
주소100010015000
이름ab-
실제 저장된 데이터@5000@5000‘core javascript’

변수 a는 5000 주소의 데이터를 바라보기 때문에 변수 b에는 5000 이라는 주소값이 저장된다.

그렇다면 객체를 복사하면 어떻게 되는가

1
2
3
/* 예제 4 */
var a = {title: 'core javascript', type: 'text book'};
var b = a;
주소10001001
이름ab
실제 저장된 데이터@5000@5000
주소500050015002
이름-titletype 
실제 저장된 데이터@7000~@7001@7000@7001 
주소70007001
이름--
실제 저장된 데이터‘core javascript’‘text book’

변수 b에 a를 복사했기 때문에 주소값 @5000이 할당되어 있다. 그런데 여기서 만약 변수 a의 type 프로퍼티 값을 바꾼다면,

1
2
3
4
/* 예제 5 */
var a = {title: 'core javascript', type: 'text book'};
var b = a;
a.type = 'e-book';
주소500050015002
이름-titletype 
실제 저장된 데이터@7000~@7001@7000@7002 
주소700070017002
이름---
실제 저장된 데이터‘core javascript’‘text book’‘e-book’

이렇게 새로운 @7002라는 주소가 추가되고, type 프로퍼티는 @7002 주소를 참조하게 된다.

그렇다면 변수 a, b 각각 메모리에 있는 데이터는 어떻게 됬을까?

주소10001001
이름ab
실제 저장된 데이터@5000@5000

둘 다 변하지 않았기 때문에 b는 여전히 a와 같은 객체 주소값(@5000)을 바라보게 되고, 실제 객체 b의 값은 변수 a와 동일한 값으로 나온다.

1
2
3
4
5
6
/* 예제 5 */
var a = {title: 'core javascript', type: 'text book'};
var b = a;
a.type = 'e-book';
console.log(b);
// {title: 'core javascript', type: 'e-book'}

이게 단순 기본형 데이터를 갖는 변수와 참조형 데이터를 갖는 변수의 차이점이다.

대부분 인터넷이나 책 에서는 ‘기본형은 값을 복사하고, 참조형은 주소값을 복사한다. 때문에 참조형은 깊은복사&얕은복사로 나누어진다.’ 라고 하지만 사실은 둘 다 주소값을 참조하기 때문에 복사할 때도 주소값을 복사하는 셈이다.

어떻게 해야 b가 더 이상 a와 동일한 주소값을 갖지 않도록 할 수 있을까?

얕은 복사&깊은 복사

얕은 복사는 바로 아래 단계의 값만 복사하고 깊은 복사는 내부의 모든 값을 하나하나 찾아서 전부 복사한다.

얕은 복사의 예시는 예제 5를 참조하면 되고, 깊은 복사에 대한 예제 코드를 보자.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
/* 예제 6 */
var a = {title: 'core javascript', type: 'text book'};
var b = deepCopy(a);

function deepCopy(obj) {
	var copyObj = {};
	if (typeof obj === 'object' && (obj !== null || undefined)) {
		for (var prop in obj) {
			copyObj[prop] = deepCopy[prop];
		}
	} else {
		copyObj = obj;
	}
	return copyObj;
}

이 예제에서는 계속 deepCopy 함수를 거쳐서 프로퍼티에 직접적으로 객체가 아닌 프로퍼티의 주소값을 전달해주기 때문에 a의 객체가 변경되어도 b는 영향을 받지 않는다.

이렇게 function을 직접 짜도 좋지만, 아주 간단한 방법으로는 JSON.stringify()가 있다. 다만 이 메소드는 JSON이 허용하는 데이터 타입에 한해서만 가능하다.

JSON이 허용하는 데이터 타입은 Object, Array, Number, String, Boolean, Null이 있다.

NULL&undefined

1차원적으로는 null, undefined 모두 값이 없다고 표현하는 것 같지만, 사실은 아니다.

자바 스크립트 엔진이 자동으로 undefined 를 부여하는 경우는 다음과 같다.

  • 값을 대입하지 않은 변수에 접근할 때,
  • 객체 내부에 없는 프로퍼티에 접근할 때
  • return으로 반환하는 값이 없는 function 호출하는 경우
1
2
3
4
5
6
/* 예제 7 */
var a = {title: 'core javascript', type: 'text book'};
console.log(a.test); // undefined

var b = ['a', 'b', 'c'];
console.log(b[3]); // undefined

var 변수는 변수를 선언하면 바로 undefined 를 할당하지만,

let, const 에는 undefined 를 할당하지 않은 채로 초기화를 마치고 특정 값을 할당하기 전까지는 해당 변수에 접근할 수 없다.

null은 비어있음을 명시적으로 나타내기 때문에 undefined보다 보다 명확하게 비어있음을 나타내고자 할 때 사용한다.

This post is licensed under CC BY 4.0 by the author.

Javascript Error 객체를 살펴보자.

iOS 14,15 버전 input 태그 이슈