원시 타입과 객체

박재성·2021년 12월 28일
0

자바스크립트 객체를 알기 위해 알아야 할 개념들
프로퍼티, key, value, 함수, 인스턴스, 클래스, 생성 방법, 원시타입

원시 값은 값이 저장, 객체는 참조 값이 저장

원시는 pass by value, 객체는 pass by reference

불변성

깊은 복사, 얕은 복사 deep copy, shallow copy

자바스크립트는 객체?

객체는 'key'와 'value'로 이뤄진 'property'의 집합이다.

이게 끝인줄 알았다. 객체는 저런 타입의 데이터구나 생각하고 끝났었는데, 이 말을 보고나서 생각이 달라졌다.

자바스크립트를 구성하는 거의 모든 것이 객체다

So what?이라는 질문을 던지고 싶다.

자바스크립트는 객체를 어떻게 이용하는지, 왜 객체를 이용하는지 자바스크립트를 이루는 데이터, 원시타입과 객체의 개념을 통해 이해해보자.

원시 값

자바스크립트의 데이터는 크게 원시타입과 객체타입으로 구분할 수 있습니다.

원시타입은
- 숫자, 문자열, 불리언, null, undefined,symbol

객체타입은
-객체

원시타입과 객체의 특징

각 데이터 타입의 특징은 원시타입은 변경이 불가능 하지만 객체타입은 변경이 가능합니다.

값을 변경할 수 있다는 것은 새로운 메모리에 값을 할당하는 것이 아니라 기존의 값을 변경하는 것입니다.

앞선 블로그에서 자바스크립트는 재할당을 할 경우 새로운 메모리에 값을 대입한다고 공부했습니다.

var v = 1
var v = 2
var v = 3

이와 같이 변수 v에 값을 재할당 하면, v에 확보된 메모리에 저장된 1이 2로 할당 되는 것이 아닌, 새로 확보한 메모리에 2가 할당됩니다.

즉, 원시 값을 변수에 할당하면 '값'이 저장 됩니다.

객체를 변수에 할당하면 같은 방식으로 동작할까요?

아닙니다. 객체를 할당한 변수는 객체를 가르키는 메모리 참조값이 저장됩니다.

이를 종합하면,

var v = 1
var v2= v
var v3= v2
-------------------
var obj = {...}
var o = obj

원시 값이 할당된 변수를 다른 변수에 할당하면 값이 복사되어 전달되고, 객체가 할당된 변수를 다른 변수에 할당하면 객체의 참조 값이 복사되어 전달됩니다.

이를 각각, pass by value, pass by reference라고 합니다.

자바스크립트에는 정확한 명칭이 없지만 개념상 일맥상통이라 위 용어를 사용했습니다.

불변성

위에서 원시 값은 변경 불가능 하다고 했습니다. 이는 변수에 확보된 메모리에 저장된 값을 변경할 수 없다는 의미입니다.

원시 값이 저장된 변수에 다른 값을 재할당 하면 새로운 메모리 변수를 할당하고, 그 메모리에 값을 저장하고, 기존의 값은 해제합니다.

이러한 특성을 불변성이라 합니다.

문자열

원시타입 중에는 문자열도 있습니다. c언어에서는 문자열이란 데이터 타입이 없고, 문자열을 배열처리 해서 문자열을 사용합니다.

원시타입의 특징들을 조합하면 자바스크립트의 문자열은 위에서 공부한 것과 약간의 차이가 있습니다.

문자열은 원시타입이지만 객체처럼 사용하는 특징이 있습니다.

예를 들어, length 프로퍼티를 갖고, 인덱스를 이용해 문자에 접근이 가능하고, for문을 통해 문자열을 순회할 수 있습니다. 객체에서 사용하는 방식을 원시타입에서도 사용할 수 있습니다.

원시타입이 객체일 수도 있는 사실에 큰 혼란이 오지만,

해당 개념은 래퍼객체를 알아야 하므로, 21절을 공부하고 다루겠습니다.

pass by value

원시 타입은 기본적으로 값에 의한 전달이 이뤄집니다.

var point = 80
var copy = point;

console.log(point, copy) ---- 1

point = 100

console.log(point, copy) ---- 2

2번에서 어떤 결과 값이 나오고, 왜 그렇게 나오는지가 중요한 핵심입니다.

1번에서는 변수 copy가 point의 값이 할당 됐습니다. 즉, copy에는 80이 할당 됐습니다.

이때, copy와 point는 같은 메모리를 사용하지 않습니다. point를 copy에 할당하면 point의 값만 복사하여, copy를 담을 메모리를 할당하고 해당 메모리에 값을 할당합니다.

그리고 point에 100을 재할당 하면, copy와 point는 어떤 관계도 없으므로 copy에는 아무런 변화가 없습니다.

사실은 pass by reference

하지만 한 가지 이상한 점이 있습니다. 분명 '값에 의한 전달이지만' 결국에는 참조에 의한 전달이 아닌가 생각이 들었습니다.

변수라는 식별자는 값을 저장하지 않습니다. 값은 메모리 공간에 저장된 것이고, 식별자는 메모리 주소를 기억해서 어떤 값을 구별할 수 있습니다.

원시 타입이 할당된 변수를 다른 변수에 할당하면, 새 변수의 식별자는 할당된 변수의 메모리에 접근해 값을 식별을 하기 때문에 주소에 의해 전달이 이뤄졌다고 볼 수 있습니다.

따라서, 자바스크립트에서 값은 pass by reference 형식으로 전달됩니다.

결론적으로, pass by reference에 의해 값이 전달되어도, 두 원시 값은 서로 다른 메모리 공간에 할당되어, 어느 한쪽의 값을 변경해도 영향을 줄 수 없습니다.

객체

자바스크립트 객체는 property의 key를 index로 사용하는 해시 테이블입니다. 해시 테이블은 다음 블로그에서 작성합니다.

위에서 객체는 변경 가능한 값이라고 설명했습니다. 객체를 할당한 변수가 가르키는 메모리 주소에 접근하면 객체가 할당된 참조 값에 접근할 수 있습니다.

원시 타입과 차이를 보인다면, 원시 타입은 변수가 가르키는 메모리에 값이 있었다면, 객체는 변수가 가르키는 메모리에 객체를 가르키는 메모리 값(참조 값) 이 들어있습니다.

var obj = {
	name: 'park',
}
obj.name = 'jae'
obj.address = 'seoul'

이렇게 메모리에 저장된 객체에 데이터를 동적으로 추가하거나, 변경할 수 있습니다.

만약에 원시타입처럼 재할당을 할 때마다 값을 복사해서 새롭게 생성하면, 원시타입보다 크기가 크고, 복잡한 객체는 복사해서 생성하는 메모리의 효율이 떨어질 수 있다.

그래서 객체는 원시타입과는 다르게 변경이 가능하게 설계한게 아닐까 생각합니다.

하지만 이러한 특성 때문에 객체는 여러 식별자가 동시에 공유할 수 있게 되면서, 구조적인 부작용이 있습니다.

부작용

객체는 여러개의 식별자가 동시에 하나의 객체를 공유할 수 있습니다.

var o = {
	name: 'park',
}
var copy = o

객체를 할당한 변수를 다른 변수에 할당하면, copy, o 변수는 같은 객체를 가르키는 참조 값을 메모리에 저장합니다.

즉, o에서 객체 프로퍼티를 조작하거나, copy에서 프로퍼티를 조작해도 둘 다 영향을 받게 됩니다.

결론

객체와 원시 타입의 동작 원리는 두 가지로 pass by value, reference가 있다. 결국 둘 다 식별자가 메모리를 기억하고, 그 메모리의 저장되어 있는 값을 복사해서 전달하는 것은 같습니다.

다만, 그 값이 원시 값인지, 객체를 가르키는 참조 값인지 차이가 납니다.

따라서 자바스크립트는 메모리에 의한 전달입니다.

자바스크립트는 모든게 포인터라는 것이 이제 이해가 됐다.

profile
개발, 정복

0개의 댓글