자바스크립트

원시타입과 레퍼런스 타입의 차이

jdy8739 2021. 12. 27. 20:47

자바스크립트도 자바와 마찬가지로 원시타입, 레퍼런스타입 변수가 있다.

 

원시타입은 말 그대로 String, Number이 들어간다.

 

자바에서는 좀 더 많이 char, int, float, long 등 더 세분화돼있다.

 

어쨋든 원시타입은 값 자체가 변수에 할당되는 타입들을 말하고, 객체인 변수가 참조형 변수가 된다는 것은

대부분의 프로그래밍 언어에서 동일하다.

 

자바스크립트에서는 Array와 Object가 참조형 변수이다.

 

참조형 변수는 변수의 값 자체가 아니라 메모리 주소값을 갖는건 다 알것이다.

 

원시타입 변수는 값 자체이기때문에 복사가 단순하지만,

 

참조형 변수는 할당과 복사에 있어서 조금 생각을 해줘야한다.

 

const arr1 = [1, 3, 5];

const arr2;

 

arr2 = arr1;

 

이런식으로 arr2에 arr1을 대입한다면 arr2의 값 자체가 복사되어 들어가는것이아니라, 

arr1에 있는 메모리 주소가 arr2에 복사돼 두 변수가 같은 값을 공유하게된다.

 

그래서 아예 재할당을 제외하고(물론 const라 재할당이 불가능) push나 splice 또는 객체일 경우 프로퍼티의 값을

변경했을 때 둘의 값이 같이 변경된다.

 

왜냐면 두 변수는 결국 하나의 객체만을 공유하는것이기때문이다. 

 

그래서 객체나 배열을 복사할 때, 주소값이 아니라 값 자체를 불러와 복사하기 위해

spread operator나 stringify()를 활용하는것이다.

 

그러면 같은 주소값을 공유하지않는다.

 

그래서...

 

const obj1 = { name: 'Jack' };

const obj2 = { name: 'Jack' };

 

obj1 == obj2 는 false가 나온다. 

단순히 프로퍼티의 key와 value값이 같을 뿐, 두 객체는 다른 주소에서 살고있는 별개이기때문이다.

 

 

좀더 헷갈리는 예를 보자.

 

const person = { name: 'Saul' };

이라는 객체를

 

function changeName(obj) {

    obj = { name: 'Jack' };

};

이렇게 객체의 내용을 바꾸는 함수를 생성하고

 

chnageName(person);

이렇게 넣는다면 어떻게될까?

person.name이 과연 바뀔것인가?

 

정답은 바뀌지않는다.

저 세 코드를 모두 돌리고 console.log(person.name);을 출력하면,

 

콘솔창에 그대로 'Saul'이 나온다.

 

왜냐면 changeName에 person을 넣었을 때 person은 obj가 되는게 아니기때문이다.

 

obj는 changeName 함수에서 살고 죽는 지역변수일뿐이다.

 

changeName(person);을 실행할 때 obj와 person이 같아지는게아니라, 단순히 person이라는 변수값이 obj로 복사되는것뿐이다.

 

person에서 obj로 복사되는 값은 { name: 'Saul' }라는 객체의 내용이 들어있는 주소값이다.

 

그럼 함수가 실행될 때 obj에는 저 객체를 가르키는 aaa123xxxx 뭐 이런 주소값이 들어있는데, obj의 내용을

 

obj = { name: 'Jack' }; 이런식으로 재할당해주고있다.

 

그럼 { name: 'Saul' }을 가르키는 주소는 사라지고 { name: 'Jack' }를 가르키는 메모리주소로 obj값이 바뀐다.

 

그러니 결국 외부의 person 객체는 아무런 영향도 받지않는것이다!

 

person에 든 주소값을 단순히 obj에 전달하고 obj의 값이 재할당됐을 뿐, 아무런 수정이 없었기때문이다.

 

 

하지만 만약

 

function changeName(obj) {

    obj.name = 'Jack';

};

 

이렇게 구체적으로 프로퍼티를 바꿔버리면 어떻게될까?

 

저런 함수로 chnageName(person);를 실행하면 person.name의 값은 바뀐다.

 

이유를 설명하자면, 일단 obj에 .이 찍혔다.

그럼 obj는 안에 변수나 함수같은 프로퍼티를 가진 객체라는 뜻으로 컴퓨터는 obj에 든 주소값으로 실제 객체를 호출한다.

 

그다음 찾은 객체에 name이라는 프로퍼티를 탐색하고 찾아서 할당된 값으로 바꿔버리기때문이다.

 

그래서 console.log(person);을 출력하면 { name: 'Jack' }이 출력된다.