본문 바로가기

JavaScript

원시값과 참조값

[22.12.23 수정]

 

JavaScript에는 자료형 또는 값에 두가지 카테고리가 있습니다.

 

즉, 불리언, 문자열, 숫자, 객체 등은 원시값과 참조값으로 2개의 카테고리로 나눌 수 있습니다.

 

 

 

JavaScript의 타입과 자료구조 - JavaScript | MDN

모든 프로그래밍 언어에는 내장된 자료구조가 존재하지만 보통 그 내용은 언어마다 다릅니다. 이 글에서는 JavaScript에서 사용할 수 있는 내장 자료구조와 그 속성에 대해 알아보겠습니다. 그러

developer.mozilla.org

 


원시값

 

데이터의 6가지 타입은 원시값에 속합니다. (문자열, 숫자, boolean, null, undefined, symbol) 우리가 만드는 모든 숫자는 변수로 저장되어 계산에 사용됩니다.

 

이는 JavaScript 또는 브라우저에 의해 원시값으로 만들어집니다. 원시값은 상대적으로 짧게 동작하기 때문에 보통 stack에 저장되어 집니다.

(보통은 Stack에 저장되지만 실행 시간이 긴 경우 Heep에 저장 됩니다.)

 

JavaScript는 원시값을 상대적으로 쉽게 제거할 수 있고, 다시 복사하는 것도 적은 메모리 사용으로도 가능합니다. 변수를 복사한다는 것은 원시값을 가진 새로운 변수에 할당하고, 실제로 복사되는 것은 저장된 원시값입니다.

 

아래 첨부된 콘솔에 작성한 코드를 같이 보시면 쉽게 이해하실 수 있으실 것입니다.

변수 name에 'LSH'(원시값)을 할당하고, 다른 변수 anotherUser에 복사하여 할당하였습니다. 변수 anotherUser는 'LSH'를 가지고 있는 상태입니다. 추가로 변수 name에 'RATI'라는 값을 재할당해주었지만, 변수 anotherUser는 여전히 값이 'LSH'입니다.

 

변수나 매개변수에 있는 값을 이용할 때 그 값을 다른 변수에 저장하면 원래 변수의 값을 변경하더라도 해당 값을 저장한 다른 변수에서는 값이 변하지 않습니다. 원시값은 값으로 복사되었고, 다른 변수에 복사된 값을 할당할 때 JavaScript와 브라우저에 복사된 값을 이용하라고 지시한 것이기 때문입니다.

 

즉, 변수 name에 저장된 값을 복사하여 값 자체를 변수 anotherUser에 저장한 것입니다. 모든 문자열과 숫자는 어딘가에 저장되어야하고, 어디에 저장되는지 우리는 예상할 수 없기 때문에 JavaScript는 항상 복사본을 만들어 두고 새로운 변수에 저장하고 싶을 때 메모리에 있는 복사된 값을 메모리 내에 값은 곳에 저장된 값을 저장합니다.

 

 

 


참조값

 

객체는 만들 때 상대적으로 메모리 사용이 많습니다. 자체적으로 만드는 객체나 브라우저에 내장되어 사용할 수 있는 객체는 관리하기가 복잡해서 만드는데 더 오래걸리고 더 많은 메모리를 차지합니다.

 

따라서 브라우저는 객체를 보통 Heep에 저장하는데, 변수에 값 자체가 아닌 메모리 공간의 주소를 가르키는 포인터를 저장합니다. 원시값의 경우 메모리에 해당 값을 그대로 저장하지만, 참조값의 경우 메모리에 값 대신 Heep 어딘가에 저장된 메모리 공간의 주소를 저장합니다. 

 

*저장된 메모리 공간의 주소를 가르키는 것을 포인터라고 할 수 있습니다.

 

간단하게 말하면 메모리에 저장된 객체를 참조하는 것입니다. 따라서 참조값을 가진 변수를 복사하여 다른 변수에 할당하면 값자체를 할당하는 것이 아닌 변수가 가르키는 포인터를 복사하여 할당하는 것입니다.

 

아래 콘솔에 입력한 코드를 함께 보시면 이해하기 쉬우실 것입니다.

변수 hobbies는 ['Sport']라는 배열을 할당 받은 것이 아닌 ['Sport']가 저장된 메모리 공간의 주소를 가르키는 포인터를 할당 받은 것입니다.

 

변수 newHobbies는 hobbies의 ['Sport']라는 배열을 할당 받은 것이 아닌 hobbies가 할당받은 포인터를 할당받은 것입니다.

 

때문에 hobbies가 참조하는 배열에 'Cooking'을 push하게되면, newHobbies도 같은 배열을 참조하기 때문에 push된 'Cooking'을 가지게 됩니다.

 

만약 위의 코드에서 변수(let) 대신 상수(const)를 사용했다면 push가 가능할까요?

원래 상수는 값을 변경할 수 없지만 상수에 저장된 값이 참조값이라면 가능합니다.

 

상수 hobbies와 상수 newBobbies에 할당된 것은 메모리 공간의 주소입니다. push를 하는것은 메모리 공간에 있는 객체에  값을 추가하는 것이기 때문에 push를 한다고해서 상수에 담긴 메모리 공간의 주소가 바뀌는 것은 아닙니다. 때문에 여전히 두개의 상수는 같은 참조값을 가지고 있습니다.

 

 

변수 person과 변수 newperson은 객체 {name : 'SH', age :38}를 저장한 같은 메모리 공간 주소를 할당 받았기 때문 newPerson.age = 28 로 age의 value를 값을 수정하게 되면 위와 같은 결과가 나옵니다.

(person이 참조하는 객체의 저장된 주소가 같기 때문입니다.)

 

 

 

 

 

'JavaScript' 카테고리의 다른 글

Garbage Collection  (0) 2022.12.23
lodash를 활용한 깊은 복사  (0) 2022.12.23
Symbol, BigInt  (0) 2022.12.23
History  (0) 2022.12.23
Location  (0) 2022.12.22