ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [JavaScript] 자바스크립트 값, 레퍼런스
    WIL 2023. 7. 27. 02:52

    먼저 자바스크립트 타입은 크게 2가지로 나눌 수 있다.

     

    원시 타입

    • undefined
    • null
    • string
    • number
    • boolean
    • symbol(ES6 추가)

     

    객체 타입

    • function
    • array
    • object

     

    타입에 대해서 먼저 알아본 이유는 자바스크립트는 값의 타입으로 값-복사, 레퍼런스-복사를 결정하기 때문이다.

     

    예를 들어보자.

    var a = 2;
    var b = a; // b가 a에 값을 복사한다.
    b++;
    a; // 2
    b; // 3
    
    var c = [1,2,3]
    var d = c; // d는 공유된 [1,2,3] 값의 레퍼런스다.
    d.push(4);
    c; // [1,2,3,4]
    d; // [1,2,3,4]

    예제에서 a 변수에 할당한 값 2에 타입은 number로 원시값이다.

    b 변수에 a 변수를 할당할때 a에 값(2)을 복사해 새로운 변수 b에 값을 할당한 것으로,

    서로 다른 변수에 값이 복사가 된것이지 같은 값을 가지고 있는게 아니다.

     

    따라서 변수  b에 값을 더했을때는 a에 값이 같이 변하지 않는다.

    자바스크립트는 어떤 변수가 다른 변수를 참조할 수 없다.

    하지만 c와 d 변수를 보면 c 변수에 있는 [1,2,3] 값을 d 변수에서 값을 변경 하였을때,

    c 변수에 있는 값 같이 변경이 된걸 볼 수 있다.

     

    왜 a와 b 변수랑은 다르게 값이 변경이 되는걸까?

     

    이유는 위 에서 말한 객체 타입에 타입들은 c에 할당한 [1,2,3] 값을 d 변수도 같이 공유를 하고 있기 때문이다.

    더 자세히 말해본다면 c 변수와 d 변수는 값 [1,2,3]에 대한 개별 레퍼런스이기 때문이다.

     

    중요한건 c 변수와 d 변수가 [1,2,3] 값을 소유 하고 있는것이 아닌 값을 동등하게 참조하고 있다는것이다.

    따라서, d 변수가 참조 하고 있는 값 [1,2,3]을 수정하였을때 c 변수도 같은 값을 참조하고 있기에 같이 값이 변경이 되는것이다.

    해당 동작을 잘 인지하고 있어야 의도하지 않은 값 변경을 막을 수 있다.

     

    함수 인자로 예를 들어보자.

    function foo(x) {
    	x.push(4);
        x; // [1,2,3,4]
        
        x = [4,5,6]
        x.push(7);
        x; // [4,5,6,7]
    }
    
    var a = [1,2,3];
    
    foo(a);
    
    a; // [4,5,6,7]이 아닌 [1,2,3,4]

    a 변수를 인자로 넘긴다면 a의 레퍼런스 사본은 x에 할당이 된다.

    그렇다면 x와 a는 동일한 값을 참조하고 있게 되는것이다.

     

    위 예제와 같이 a와 동일 값을 바라보는 인자 x에 값을 변경한다면

    a에 변수가 참조하고 있는 값이 변경되므로 a변수 값이 같이 변경이 되지만

    x 인자를 새로운 값 [4,5,6]을 할당을 한다면 x는 a와 같은 값을 참조하는 것이 아닌

    새로 추가한 값 [4,5,6]을 참조하고 있어 a가 참조하고 있는 값에는 영향을 주지 않는것이다.

     

    해당 예제로 2가지를 알 수 있다.

    하나는 같은 참조 값을 가진 변수를 다른 스코프에서 변경을 한다 해도 참조 하는 값이 같다면 같이 변경이 된다는것이다.

    이런 현상은 원한지 않은 동작을 발생 시킬 수 있고 디버깅이 어려울 수 있다.

     

    다른 하는 위 현상을 해결 할 수 있는 방법이다. 바로 새로운 참조 값을 만들면 되는 것이다.

    배열 같은 경우에는 Array.mapArray.filter와 같은 메서드(네이티브 배열 함수)들은

    내부 적으로 원본 대신 복사된 배열로 작업이 되어 원본 배열(참조 값)을 건들지 않고,

    새로운 배열(참조 값)로 반환을 하게 되어 위 현상 과 같은 상황을 해결 할 수 있는것이다.

     

    값-복사, 레퍼런스-복사는 우리의 마음대로 경정하는것이 아니고 전적으로 값의 타입을 보고 엔진의 재량으로 결정된다.

    즉, 우리가 알 수있는 유일한 단서는 값의 타입뿐이고 사용할 값 타입을 잘 정해야 의도한 동작을 만들 수 있다.

     


    YOU DON'T KNOW JS 책을 보고 정리를 하며 글을 쓰니 더 머리에 남아 있는거 같다.

    또 책을 보고 정리해보자.

Designed by Tistory.