ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • 자바스크립트 원시 값(Primitives values) : index[ ]로 string을 바꿀 수 없다!
    Front-end/Javascript 2021. 7. 21. 14:08
    반응형

     

    오늘 아침부터 함께 스터디하며 도움을 받고 있는 분과 함께 재미있는 이야기를 했다.

    요즘 Javascript와 Node.js의 내부 사정에 대해서 공부를 하고 있는데, 그러다보니 이런 문제가 나온 것 같다.

    아마 당연하다고 생각하시는 분들도 있겠지만, 의외로 주니어의 경우 모르는 분들 또한 많을 것 같다고 생각 되어 정리를 해둔다.

     

    첫 번째 문제는 이것이었다.

    var name1 = { name: "javascript" };
    var name2 = { name: "javascript" };
    
    name1 == name2

    자 이것의 답은 무엇일까?

    name1과 name2는 같은 것일까?

     

    이전에 정리해 둔 포스팅인 이벤트루프 편을 읽어보시면 조금 더 빨리 감을 잡을 수 있을 것이다!

    정답은 바로! false 이다.

    /* 잠깐 상식 타임!! == , === 각각 뭐가 다른 것일까? */

    == : 변수만 비교하는 것으로 좌변의 타입으로 우변을 타입 캐스팅 한 다음 비교한다.
    타입캐스팅은 타입을 변환시켜주는 것인데 그로 인해서 123 === "123" 은 true가 나온다.

    === : 변수와 데이터타입 모두 비교한다. ===의 경우 타입캐스팅을 시켜주지 않기 때문에 123 === "123"은 false가 나온다

     

    여기서 많은 분들이 "어? { name: "javascript } 라고 하면 같은것 아닌가? 라는 생각을 할 수 있다.

    그렇다면 위의 이벤트루프 편 중간부분 쯤을 잠깐 살펴보기 바란다.

     

    이 문제를 해결하기 전에 우선 두번째 문제부터 살펴보자!

    var dogs = "Marry"
    
    dogs[1] = "e"
    
    console.log(dogs)

    자, 이렇게 dogs의 한 부분만 바꾸려고 한다.

    바로 a부분을 e로 바꾸고 싶은 것이다.

    그렇다면 이렇게 console.log를 찍어보면 답이 뭐라고 나올까?

    Merry라고 나올까?

    정답은... "원본과 똑같다" 즉, 바뀌지 않는다.

     

    이 두 가지 문제는 같은 지식을 바라보고 있다.

    바로 primitives와 reference 이다.

     

    Primitives values는 MDN에서 보면 우리말로 원시값 이라고 나와있다.

    이러한 원시 값의 종류로는 string, number, bigInt, boolean, undefined, symbol, null이 존재한다.

    이는 메모리 안의 스택에 위치하고 있는데, JAVA의 경우 Primitives pool 이라고 하여 이러한 원시값이 존재하는 공간이 있지만 Javascript에서는 특별히 없으므로 그냥 stack에 위치하고 있다 정도만 생각해도 괜찮을 것 같다.

     

    만약 우리가 Primitives를 사용하게 되면 stack에 있는 것을 복사해와서 값을 그대로 할당하여 사용하게 되고, stack에 쌓이게 된다.

    그러나 primitive value가 아닌 것(reference value)은 Heap에 저장이 된다.

    대표적으로 객체, 배열, 함수와 같은 것이 있다.

    이런 것들은 Heap memory에 생성 되며 스택에는 변수들이 있는데 그 변수가 Heap memory에 생성 된 그 공간을 가리키게 된다.

     


    자, 이제 다시 첫 번째 문제를 보자!

    var name1 = { name: "javascript" };
    var name2 = { name: "javascript" };
    
    name1 == name2

    name1과 name2는 서로 같은데 왜 false가 나올까?

    바로 객체이기 때문이다.

    객체는 reference value이다!

    그렇기 때문에 Heap에 저장이 되며, { name: "javascript" } 라는 것이 우리 눈에 같아 보여서 그렇지 사실상 서로 다른 곳에 똑같은 것을 만들어서 가리키고 있는 것이다.

    다시말해, 이런 형태를 하고 있는 것이다.

    ( 그림을 표현하고자해서 이렇게 그린 것이지 stack은 아래에서 위로 쌓이고, 위에서부터 실행되는 반면, Heap은 구조화 되지 않은 넓은 메모리 영역일 뿐이다 )

    그렇기 때문에 name1과 name2는 결국 다른 것이라는 결론이 나온다.


    자, 그렇다면 두 번째 문제도 이어서 보자!

    var dogs = "Marry"
    
    dogs[1] = "e"
    
    console.log(dogs)

    이렇게 console.log를 찍어보면 바뀌지 않은 Marry가 나온다.

    그 이유가 무엇일까?

     

    이 또한 primitive value, reference value를 알고 있다면 이해할 수 있을 것이다.

    primitive value의 종류 중에는 string이 있었고, "Marry"는 string이다.

    그리고 MDN에 primitive value에 대해서 찾아보면 알 수 있겠지만 아래와 같이 나온다.

    All Primitives are immutable. they cannot be altered.

    쉽게 말해, 원시값은 불변하다는 것이다.

    primitive value는 stack에 저장 된 이미 만들어진 것이므로 교체를 할 수는 있지만 직접 변경이 불가하다.

     

    MDN에서 가져온 이와 유사한 또 다른 예시를 보자!

    var bar = "baz";
    console.log(bar);        // baz
    
    bar.toUpperCase();
    console.log(bar);        // baz

     

    baz를 대문자로 변경하고 싶은데 이는 불가하다.

    하지만 교체는 가능하다! 그러므로 아래와 같이 교체 할 수는 있다.

    bar = bar.toUpperCase(); // BAZ

    이렇게 하면 변경을 한 것이 아니라 원시 값에 새로운 값을 부여한 것이다.

     

    이러한 primitive value가 아닌 reference value라면 어떨까?

    var foo = [];
    console.log(foo);        // []
    
    foo.push("plugh");
    console.log(foo);        // ["plugh"]

     

    이러한 배열, 함수, 객체의 경우에는 reference value로써 변형이 가능하다!

    반응형
Designed by Tistory.