본 내용은 아래의 글을 참조하여 작성하였습니다
(https://github.com/leonardomso/33-js-concepts#3-value-types-and-reference-types)
* Pass By Value
앞선 게시글 JS 필수 개념 2 - Primitive Types (https://sdy-study.tistory.com/29) 에서도 언급했듯이,
JS 의 기본 데이터 타입을 Primitive Types 라 부르고 이에 대한 타입이 총 5개가 존재한다고 했다
(ES6 이후 추가된 Symbol 은 일단 제외한다)
5개의 primitive types (Number, Null, Undefined, String, Boolean) 은 데이터를 처리할 때
값(value) 에 근거하여 변수에 변화를 준다.
무슨 말인가 하면,
var x = 10;
var y = 'a';
var a = x;
var b = y;
|
cs |
위와 같은 4개의 변수를 선언했다고 가정해보자.
만약 변수 a, b 를 아래와 같이 다른 값으로 바꿨다고 치면,
a = 999;
b = 'Z';
|
cs |
변수 x, y 의 값은 변할까?
프로그래밍을 처음 접하는 사람이 아니라면, 당연히 바뀌지 않는다고 말할 것이다.
그리고 실제로도 4개의 변수를 각각 출력하면 변수 a,b 만 변할 뿐 변수 x, y 는 변하지 않는다.
그렇다면, 왜 변하지 않는 걸까?
이에 대한 이해를 하기 위해서는 JS 에서 Primitive Type 에 해당하는 변수를
어떤 식으로 메모리에 저장하는지를 이해해야 한다.
* 메모리
위에서 선언한 4개 변수들은 메모리의 각자 다른 부분에 저장되기 때문이다.
실제 컴퓨터의 메모리는 다른 모습으로 나타나지만
간단하게 보면 위처럼 각자 다른 공간에서 저장된다.
처음에 a = x, b = y 할 때도 서로 다른 메모리 공간에서 저장되었기 때문에
a = 999; y = 'Z' 할 때도 값이 변하지 않았던 것이다.
그렇다면 모든 변수가 이런식으로 저장되는가? 는 아니다.
위와 같은 방식은 passed by value 로 처리된 것이고,
또 다른 방식으로 passed by reference 라는 방식이 있다.
* Pass By Reference
passed by reference 방식은 위와 같은 5가지의 Primitive type 에 적용되는 것은 아니고,
Object, Array, Function 에 적용되는 방식이다.
이 방식은 앞선 passed by value 처럼
새로운 메모리를 할당해서 값을 그대로 카피하는 방식으로 만들어서 따로 관리를 하는 것 이라면,
passed by reference 는 값을 가져오는게 아니라 "메모리 주소" 를 참조하는 변수를 생성해서 처리를 하는 것이다.
예를들면, 아래의 변수를 선언했다고 하면
arr.push(1);
|
cs |
메모리 구조를 도식화 하면 아래와 같다고 가정할 수 있다.
passed by value 와 다른 점은 arr 라고 선언한 변수가 값을 가질때,
[] 에 대한 주소값을 갖는 다는 점이다.
[] 를 값으로 가지지 않는 다는 것이다.
만약 값을 추가하면 어떻게 될까?
arr.push(1);
|
cs |
위와 같이 변수 arr 의 '값' 자체는 변하지 않는다. (variable arr is static)
다만 참조하고 있는 대상의 값만 변경 될 뿐이다.
JS engine 이 arr 이 가르키는 주소를 찾아가서 그 위치에 값을 저장하기 때문이다.
다른 주소를 참조하는 변수(여기선 arr)를 새 변수에 할당하면 어떻게 될까?
* Assigning By Reference
예를들어 아래와 같이 코드를 쓰면 그 때의 메모리 구조는 어떻게 될까?
var arr = [1];
var arr2 = arr;
|
cs |
위와 같이 arr2 를 arr 를 값으로 받는 변수를 선언하면
arr2 또한 [1] 의 위치를 가르키는 변수가 된다.
그리고 arr 과 arr2 둘 중 하나라도 값을 추가하게 되면,
둘다 같은 값을 출력하게 된다.
아래에는 arr.push(2); 를 한 결과 이다.
* Reassigning Reference
참조형의 변수에 또 다시 새로운 값을 할당하는 경우는 어떻게 될까?
아래의 코드 처럼 작성한다면
var obj = { first: "a" };
obj = { second: "b" };
|
cs |
메모리 구조는 이렇게 바뀔 것이다.
obj 변수가 처음엔 메모리 주소값 100을 가르켰다가
재할당 되었으므로, obj 는 최종적으로 메모리 주소값 200을 가르키게 된다.
추가적으로 JS engine 은 Garbage Collection 기능을 가지고 있다.
위의 obj 예제는 GC(Garbage Collection) 에 의해서
메모리주소 100에 해당하는 { first: "a" } 값은 더이상 접근 불가능한 값이 되며,
GC 가 이 값을 메모리에서 제거해준다.
* GC 에 대한 더 자세한 설명은 아래의 주소들을 참조하기 바란다
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Memory_Management
https://javascript.info/garbage-collection
보통 스크립트 언어(javascript, python 등) 를 배우는 경우,
포인터에 대한 개념을 익히지 않기 때문에,
call by value, call by reference 에 대한 개념을 모르는 경우가 많다
하지만 프로그램을 작성함에 있어서,
메모리 관리에 대한 이해를 하는 것은 아주 중요하다고 생각한다.
unmanaged language 의 대명사인
java 를 배울 때도, GC 에 대한 개념을 아는 것이 필요하다고 본다
'JS' 카테고리의 다른 글
CORS (Cross Origin Resource Sharing) (0) | 2020.08.19 |
---|---|
Axios 와 Fetch (0) | 2020.08.06 |
#33가지 Javascript 필수 개념 - 4. Type Coercion (0) | 2020.08.02 |
#33가지 Javascript 필수 개념 - 2. Primitive Types (0) | 2020.07.22 |
#33가지 Javascript 필수 개념 - 1. Call Stack. (0) | 2020.07.21 |