ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • 3. 변수 선언과 데이터 할당 (참조형 데이터)
    JavaScript/3주차-데이터타입, 실행컨텍스트, this 2023. 5. 25. 11:30

     

     

    변수 선언과 데이터 할당

     

    참조형 데이터는 기본형 데이터와는 달리, 변수 할당 과정에서 obj1을 위한 별도 공간이 필요하다.

    즉, 참조형 데이터는 변수 할당 과정에서 객체의 변수 (프로퍼티)가 별도로 존재한다.

     

     

    기본형 데이터 (Number, String, Boolean, null, undefined, Symbol), 불변
    참조형 데이터  (Object의 하위요소 - Array, Funtion, Data, RegExp, Map, WeakMap, Set, WeakSet), 변함

     

    그냥 이렇게 생각하면 쉽다. a: 1, b: 'bbb'를 key-value pair 로 생각했을 때

    변수영역에 우선 변수이름 넣고

    데이터영역에 key값 순서대로, obj1을 위한 별도공간에 value값 순서대로 넣고

    데이터영역의 주소를 obj1을 위한 별도공간에 넣고, obj1을 위한 별도공간의 주소를 변수영역의 데이터에 넣는다.

    var obj1 = {
    a: 1,
    b: 'bbb',
    };

     

     

    1. 변수영역에 변수이름 obj1을 넣는다.

    2. 데이터영역에 순서대로 데이터(value값) 1, 'bbb'를 넣는다.

    3. obj1 을 위한 별도 공간에 프로퍼티(key값) a, b,를 넣고, 데이터 영역에서의 주소(5001, 5002)를 순서대로 넣는다.

    4. 변수 영역의 데이터에, obj1에 입력된 데이터 주소 (7103, 7104)을 입력한다. 7103부터 시작됨.

     

     

    그렇다면 참조형 데이터가 불변하지 않다 (가변하다, 변한다) 라고 하는 이유.

    값을 변경해보자.

    var obj1 = {
    a: 1,
    b: 'bbb',
    };
    
    //데이터를 아래와 같이 변경해보자.
    obj1.a = 2;

    obj1.a = 2; 로 프로퍼티 a가 2로 데이터가 변경됨에 따라, 주소 5001는 가비지콜렉터로 없어지고 새 주소인 5003에 2가 저장됨. 즉 프로퍼티a의 데이터 주소가 변경됨. (불변하지 않음)

     

     


    중첩 객체 (객체 안에 또 다른 객체가 들어간다)

    var obj1 = {
    x: 3,
    arr: [3, 4, 5],
    };

     

    여기서 arr은 obj1라는 객체 안에 들어가는 또다른 객체이다. arr은 참조형 데이터로써, obj1의 하위요소이며 불변하지 않다.

    변수영역에 obj1넣고, key 값인 x와 arr을 obj1을 위한 별도공간에 넣는다.

    x의 value값인 3을 첫번째 데이터영역 (주소 5001)에 넣는다. 

    arr의 value들은 arr을 위한 별도공간에 순서대로 넣는다. 여기서 arr의 값인 3, 4, 5를 넣지 않고 0, 1, 2를 넣는 이유는 arr이 배열이고, 인덱스값을 순서대로 넣기 때문이다.

    arr의 값들인 3, 4, 5는 데이터 영역에 넣는다. 첫번째 데이터 3은 이미 5001에 들어있으므로, 5002번부터 차례대로 4, 5를 넣으면 된다.

    arr의 데이터는 arr을 위한 별도공간의 첫번째 주소인 8104부터 시작하며, 

    obj1의 데이터는  obj1을 위한 별도공간의 첫번째 주소인 7103부터 시작한다.

     

     

     

    참조 카운트

    객체를 참조하는 변수나 다른 객체의 수를 나타내는 값입니다. 참조 카운트가 0인 객체는 더 이상 사용되지 않으므로, 가비지 컬렉터에 의해 메모리에서 제거된다. 가비지컬렉터(GC, Garbage Collector) 더 이상 사용되지 않는 객체를 자동으로 메모리에서 제거하는 역할을 한다. 자바스크립트는 가비지 컬렉션을 수행함으로써 개발자가 명시적으로 메모리 관리를 하지 않아도 되도록 지원한다. 자바스크립트 엔진에서 내부적으로 수행되며, 개발자는 가비지 컬렉션에 대한 직접적인 제어를 할 수 없다.

     


     

    변수 복사의 비교

     

    선언

    var a = 10;  //기본형
    var obj1 = { c: 10, d: 'ddd' };  //참조형

     

    복사

    var b = a;  //기본형
    var obj2 = obj1;  //참조형

     

    1. 선언

     

    변수영역에 a와 obj1 순서대로 할당

    a의 데이터인 10을 데이터 영역에 할당, 주소값인 5001을 변수a에 할당.

    obj1의 key값인 c 와 d를 obj1을 위한 별도영역에 넣고, value값을 데이터 값에 넣음. 

    c의 value값은 10을 중복되므로 패스, d의 value값을 주소 5002에 넣으면 됨.

    a의 데이터는 a의 데이터인 10의 주소인 5001부터 시작하며,

    obj1의 데이터는  obj1을 위한 별도공간의 첫번째 주소인 7103부터 시작한다.

     

     

     

    2. 복사

    var b = a;  //기본형
    var obj2 = obj1;  //참조형

     

    빨간색이 복사한 부분.

    변수영역에 b와 obj2를 순서대로 넣는다. var b = a 이고, var obj2 = obj1 이므로 

    기존 변수영역 a와 obj2에 있던 데이터 주소 (5001,  7103)를 그대로 가져다 쓴다.

     

     

     

    3. 복사 이후 값 변경

     

    여기서 중요한 문제!

    이제 복사는 끝났으니 복사 이후에 값을 변경해보자. (객체의 프로퍼티 변경)

    b를 15로, obj2.c를 20으로 바꿔보자.

     

    b = 15;
    obj2.c = 20;

     

    파란색글자가 값을 변경한 부분

    데이터 영역에 15가 없으므로 데이터에 새로 쓰고, 변수 b는 데이터 15의 주소값인 5003으로 변경함.

    obj2.c는 데이터 20이 없으므로 20을 데이터에 새로 쓰고,

    obj2 (obj1을 복사한 값)의 c가 위치한 obj1을 위한 별도공간 주소 7103으로 가서 그 주소를, 데이터 20이 위치한 5004로 바꿈.

     

     

    중요한 점.

    b가 a를 복사했는데, 서로 다른 데이터값을 갖고있다.

    a는 5001이므로 10이고, b는 5003이므로 15다.

    이건 상관없다

    그런데 마찬가지로 obj2도 obj1을 복사했는데, 둘다 7103으로 같은 데이터 값을 갖고있다.

     

    즉, 주소를 바로 복사해버리면, obj1이 아닌, obj2를 바꿨음에도 불구하고 obj1도 덩달아 c의 데이터가 5001에서 5004로 변경됨에 따라 원래 10이었는데 20으로 바뀐다.

     

    // 기본형 변수 복사의 결과는 다른 값!
    a !== b;
    
    // 참조형 변수 복사의 결과는 같은 값!(원하지 않았던 결과😭)
    obj1 === obj2;

     


    지금까지는 객체의 속성만 변경해봤는데

    그러면 객체의 프로퍼티(속성)을 변경하는 것이 아니라 객체 자체를 변경하는 방식으로 해보자

     

    기본형데이터와 참조형 데이터는 위와 똑같음.

    변경할 객체만 다름.

    // 기본형 데이터
    var a = 10;
    var b = a;
    
    
    // 참조형 데이터
    var obj1 = { c: 10, d: 'ddd' };
    var obj2 = obj1;
    
    
    // 변경할 객체
    b = 15;
    obj2 = { c: 20, d: 'aaa'};

     

    빨간색이 변경된 부분.

    b를 15로 변경하고,  obj2를 c는 20으로, d는 'aaa'로 변경함.

    20은 5004에 있으므로 c에 넣고, 새로 넣은 'aaa'는 5005에 있으므로 d에 넣음. 

    obj2에는 7103이었던 값을 8204로 갈아낌.

     

    이렇게 되면 obj1 !==  obj2.

    완전히 변경됨.

     

    즉 객체의 프로퍼티(속성)을 변경하는 것이 아니라 객체 자체를 변경해야 완전히 변경됨.

    댓글

Designed by Tistory.