Primitive, Reference data type

JiSuKim·2022년 3월 4일
0

객체지향 문법 시작 전 반드시 알아야할 reference, primitive data type 정리

Primitive data type(기본형)

자바스크립트의 자료형은 Primitive(기본형) & reference(참조형) 라고 분류하는데

Primitive data type들은 비객체 타입으로 자료 자체가 변수에 저장되는 자료들입니다.

데이터 복사가 일어날 때 메모리 공간을 새로 확보하여 독립적인 값을 저장합니다.

원시 타입은 불변성(immutable)을 갖고있다.

let a = 100;
a = 50;

a란 변수에 100이란 값을 할당하고 2번째 라인에서 50으로 재할당하였다. 첫 라인이 실행되면 메모리에 100이란 값이 생성되고 식별자 a는 메모리에 생성된 100의 메모리 주소를 가리킨다. 그후 두번째 라인이 실행되면 이전 메모리에 생성된 100이란 값이 50으로 수정되는것이 아닌,50이란 값을 새로운 메모리에 생성하고 a가 가리키던 메모리가 바뀌는것이다.
a란 변수에 100이란 값을 할당하고 2번째 라인에서 50으로 재할당을 해준 예시이다. 첫 라인이 실행되면 메모리에 Number타입의 100이란 값이 생성되고 식별자 a는 메모리에 생성된 100의 메모리 주소를 가리킨다. 그후 두번째 라인이 실행되면 이전에 메모리에 생성된 100이란 값이 50으로 수정되는것이 아닌, 새로운 Number타입의 50이란 값을 새로운 메모리에 생성하고 a가 가리키던 메모리가 바뀌는것이다.

즉 메모리에는 100과 50이란 값이 모두 존재하고 있으며, 앞에서 말했듯이 원시타입은 불변성을 갖고 있기 때문에 기존에 메모리에 생성된 값들은 그 자체가 변경될 수 없다. 그저 식별자와 연결 되있는 메모리가 바뀌었기에 우리 눈에는 재할당 된 것처럼 보일뿐이다.

문제 1 원시 타입의 값이 복사 될때 일어나는 일

let a = 100;
let b = a;
a = 50;

console.log(b) // 100

Reference Type(참조형)

선언한 자료형이 기본형이 아닌경우 참조형이라 보면 됩니다.

참조형에는 Class,Interface,Arrays가 있습니다.

reference data type은 자료를 변수에 직접 저장하는게 아닌,

자료가 저쪽에 있습니다 라는 화살표 (레퍼런스) 를 변수에 저장합니다.

메모리에 직접 접근이 아닌 메모리의 위치(주소)에 대한 간접적인

참조를 통해 메모리에 접근하는 데이터 타입이다.

원시타입과 가장 큰 차이점은 변수의 크기가 동적으로 변한다는 것이다. 이러한 특징 때문에 Object의 데이터 자체는 별도의 메모리 공간(heap)에 저장되며, 변수에 할당 시 데이터에 대한 주소 ( 힙(Heap) 메모리의 주소값)가 저장되기 때문에 자바스크립트 엔진이 변수가 가지고 있는 메모리 주소를 이용해서 변수의 값에 접근하게 되는것이다.

만일 let myArray = []라는 배열을 생성하면 위와 같은 일이 일어난다. 그림에서 볼 수 있듯이 원시타입의 값들은 값들이 직접적으로 저장되어 있지만, myArray (참조타입)는 Heap 메모리의 주소값이 저장되어 있다.

let myArr = [];
let copyArr = myArr;

myArr.push("hello");

console.log(copyArr); // ["hello"]

위 예제를 보면 알 수 있듯이, 참조 타입의 변수는 실제 데이터가 저장된 주소를 참조하기에 참조(reference) 타입이라고 불리는 것이다. 변수에 저장된건 'hello'가 아니라 값을 가리키는 화살표가 저장되어 있을뿐이다. 그렇기에 변수의 복사나 수정 시 참조 여부를 잘 고려해야 한다. 만일 이러한 특성을 고려하지 않은 채 중요한 정보를 담고있는 객체나 배열에 수정 및 복사를 가하게되면 원본 데이터가 예상치 못한 방향 으로 변경될 수 있으므로 항상 이를 고려하자.

예제 1 원시타입 재할당

var 숫자1 = 50;
var 숫자2 = 숫자1;
숫자1 = 100;

숫자1은 재할당했으니 100이 되고, 숫자2는 복사만 하고 변경하진 않았으니 50 입니다. 그런데 똑같은 일을 reference data type으로 진행하면 결과는 달라집니다.

예제2 레퍼런스 재할당

var 숫자1 = { age : 50} ;
var 숫자2 = 숫자1;
숫자1.age = 100;

숫자1은 재할당했으니 100이 되고, 숫자2는 복사만 하고 변경하진 않았으니 50 입니다. 맞을까요?
값은 둘다 100이 됩니다.
왜냐하면 숫자1을 복사해서 집어 넣을때 안에 있는 { age : 50} 이라는 데이커가 복사된게 아니라 데이터를 가리키는 reference (화살표)가 저장 되었습니다. 숫자1과 2는 같은 레퍼런스를 가지고 있습니다.
이런 원리 때문에 숫자1과 2는 같은 값을 공유하고 있었던 것입니다.

결론은 object, array 자료형은 등호로 복사하시면

화살표 값을 공유해버리기 때문에 문제가 일어날 수 있습니다.

그래서 constructor 문법을 쓰셔서 object를 복사 하시면 안전합니다.

예제3 레퍼런스 할당 기준

var 숫자1 = { age : 50} ;
var 숫자2 = { age : 50} ;

바로 위의 예제에서 숫자1 == 숫자2 이렇게 두개를 같다고 비교하면 true가 나올까요 false가 나올까요?

화살표가 같으면 (같은 곳을 가리키면) true가 나오고, 화살표가 같지 않으면 false가 나오기 때문입니다.
굳이 값이 같은지 비교하고 싶으면 숫자1.age와 숫자2.age을 비교하시면 됩니다.

예제 4 함수를 이용한 변경

var 숫자1 = { age : 50} ;

function 변경(obj){
  obj = { age : 100} ;
}

변경(숫자1);

이 함수는 오브젝트를 입력하면 오브젝트 내용을 { age : 100} ; 으로 재할당해주는 함수입니다.

그래서 숫자1을 집어넣어서 실행해봤습니다. 그러나 실행해봐도 숫자1은 변하지 않습니다. 왜그럴까요?

파라미터형 변수 때문에 그렇습니다.

function 변경(obj){
  obj = { age : 100} ;
}

여기에 있는 obj는 새로운 변수를 생성한다고 인식 합니다. 즉

var obj = 숫자1;

이렇게 표기되어 새로운 변수가 생성되고 함수가 끝나면서 사라집니다.

var 숫자1 = { age : 50} ;
console.log(숫자1); // { age : 50}
function 변경(obj) {
  obj = { age : 100} ;
  console.log(obj); // { age : 100} 
}

변경(숫자1);
console.log(숫자1); // { age : 50}

이런식으로 함수 내부에서 생성되고 소멸되는 변수가 생기게 됩니다.

마지막 문제

var 숫자1 = { age : 50} ;
console.log(숫자1); // ?
function 변경(obj) {
  obj.age = 100 ;
  console.log(obj); // ?
}

변경(숫자1);
console.log(숫자1); // ?

정답은 직접 해보시길 바랍니다.

0개의 댓글