ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • 항해 99 / 자바스크립트 언어의 특성 알아보기... 2
    항해99 2022. 7. 21. 20:20

    자바스크립트 객체와 불변성이란?

    • 기본형 데이터와 참조형 데이터

    기본형과 참조형을 구분하는 기준

    데이터 타입의 종류는 크게 기본형과 참조형 2가지로 나뉜다. 

    기본형과 참조형을 구분 짓는 가장 큰 점은 실제 값 전체 복사 vs 실제 값이 들어있는 주소 값 복사이다. 

     

    - 기본형 (copy value of a)

    let a = 1;
    let b = a;
    
    a += 10;
    console.log(a) //11
    console.log(b) //1

     

     

    기본형 데이터에는

    앞서 얘기한 숫자, 문자열, boolean, null, undefined, symbol을 얘기하는 데 이는 모두 불변값이다.

    그중 숫자와 문자열을 예로 들어 불변성의 개념을 알아보자

    var a ='abc';	
    a= a + 'def';	
    var b = 5;	
    var c = 5;
    b = 7;

    a에 문자열 'abc' 할당

    그 뒤에 'def'를 추가 이때 a에 있는 'abc'가 바뀌는 것이 아니라 
    메모리의 데이터 영역에서 새로운 문자열 'abcdef'를 만들어
    영역의 주소를 변수 a에 저장함


     b에 숫자 5를 할당

    그러면 컴퓨터는 일단 데이터 영역에서 5를 찾고,없으면 데이터 영역에 공간을 하나 만들어 저장함

     그 후 데이터 영역의 주소를 b에 저장함


    /변수c에 b와 같은 5를 할당하려고 한다. 값을 할당하기 위해서
    컴퓨터는 데이터 영역에서 5를 찾는데 위에서 이미 만들어 놓은 값이 있으니
    그 주소 값을 변수 c에도 할당 


    변수 b의 값을 7로 바꾸고자 한다 그러면 기존에 데이터에 저장된

     5를 7로 바꾸는 것이 아니라 기존에 저장했던 7을 찾아서 있으면 재활용,
    없으면 새로 만들어 위치를 b에 저장 

     

     

    이처럼 문자열과 숫자 값은 한번 만든 값을 바꿀 수 없고, 만약 변수 영역에 저장된 값을 변경하고 싶다면,

    데이터 영역에서 새로 만드는 곳을 연결해서 이뤄진다.

    이것이 불변값의 성질이다. 

     

     

    -참조형 ( a has address of  "{ x : 1}" )

    let a = { x : 1 };
    let b = a;
    
    a.x += 10;
    console.log(a.x); //11
    console.log(b.x) //11

    기본형과 다르게 let b = a; 코드를 통해 {x : 1} 의 주소 값이 b라는 변수에 담겼다. 

    a, b를 콘솔로 찍어보면 a값만 변화시켰지만, b값도 +10이 된 것을 알 수 있다.

    즉 a, b는 서로 영향을 받고 있는 것을 볼 수 있다. 

     

     

    다른 예시로 세세하게 알아보자

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

    변수 영역

    주소 1001 1002 1003 1004 ... ...
    데이터   이름 : obj1
    값 : @5001
           

     

    데이터 영역

    주소 5001 5002 5003 5004 ... ...
    데이터 @7103 ~ ?   1 'bbb'    

     

    객체 @5001의 변수 영역

    주소 7103 7104 7105 7106 ... ...
    데이터 이름 : a
    값 : @5003
    이름 : b
    값 : @5004
           

     

    출처: https://overcome-the-limits.tistory.com/262 [Plus Ultra:티스토리]

     

    컴퓨터는 우선 변수 영역의 빈 공간(@1002)을 확보 주소의 이름을 ga로 지정

     

    임의의 데이터 저장 공간(@5001)에 데이터를 저장하려고 보니 여러 개의 프로퍼티(객체 안에 있는 키:'값')

    으로 이루어져 있다. 이 데이터 그룹 내부의 프로퍼티들을 별도의 변수 영역에 주소를 저장(@7103~?)를

    @5001에 저장함

     

    @7103 및 @7104에 각각 a와 b라는 프로퍼티 이름을 지정

     

    데이터 영역에서 숫자 1을 검색(같은 숫자가 있는지 검색) 없으므로 임의의 주소

    @5003에 저장하고 이 주소를 @7103에 저장 문자열'bbb'역시 임의로 @5004에 저장하고,

    이 주소를 @7104에 저장

     

    var ga = {
    		a: 1,
            b: 'bbb'
    };
    ga.a = 2;

    5번째 줄에서 ga 변수의 a프로퍼티에다가 숫자 2를 할당하려고 할때. 데이터 영역에서 숫자 2를 검색한다.

    검색 결과가 없으므로 빈 공간인 @5005에 저장하고, 이 주소를 @7103에 저장한다. 5째 줄을 명령하기 전과 후는

    ga가 바라보고 있는 주소는 @5001로 변하지 않았다. 즉 '새로운 객체'가 만들어진 것이 아니라

    기존의 객체 내부의 값만 뀜.

     

     

    • 불변 객체를 만드는 방법

     -불변 객체가 필요한 경우

    객체에 변화를 가해도 원본이 그대로 남아있어야 하는 경우

    ex) 정보가 바뀌었으면 알림 전송하는 경우, 바뀌기 전의 정보와 바뀐 후의 정보를 보여줘야하는 경우 등

     

    -이름을 불변하게 방법

    자바스크립트에서 일반적으로 변수를 선언하는 방법은 'var'키워드를 사용하는 방식이었다.

    그러나 이 방식은 값이 변할 수 있기때문에 원본 훼손에 대한 위험에 노출되어 있었다.

    그런데 ES6 이후엔 'const'라는 키워드를 도입해 (항상 같은 변수)

    Immutability(변경불가성)을 지킬 수 있게 되었다.

     

    -객체를 불변하게 만드는 방법

    1) Object.assign(빈 객체, 복사하려는 객체)

    var obj1 = { name: 'Serzhul' }
    
    var obj2 = Object.assign({}, obj1)
    
    obj2.name = 'Daewon'
    
    // obj1 => {name: 'Serzhul'}
    // obj2 => {name: 'Daewon'}
    
    // obj1의 불변성이 유지된다.

    2) Object.freeze(불변하게 만드려는 객체)

    var obj1 = { name: 'Serzhul' }
    Object.freeze(obj1)
    obj1.name = 'Daewon'
    console.log(obj1)
    // {name: 'Serzhul'} => 속성 값이 변하지 않음

    ※ Nested object (중첩된 객체)

    Object.assign은 객체의 불변성을 지킬 수 있게 해주지만

    Nested object의 불변성은 지켜지지 못함.

    var obj1 = { name: 'Serzhul', score: [1, 2] }
    var obj2 = Object.assign({}, obj1)
    obj2.score = obj2.score.concat() // score Array의 불변성이 유지된다.
    
    obj2.score.push(3)
    
    // obj1 = {name:'Serzhul', score:[1,2]}
    // obj2 = {name:'Serzhul', score:[1,2,3]}
    • 얕은 복사와 깊은 복사

    -얕은복사

    (복사를 하고 참조도 한다.)

    참조에 의한 할딩이 이루어지므로 둘은 같은 데이터 주소를 가지고있다.

    한 마디로 같은 주소를 참조하면 얕은 복사이다.

    const obj1 = { a: 1, b: 2};
    const obj2 = obj1;
    
    console.log( obj1 === obj2 ); // true

     

    -완전히 깊은복사

    (복사를 하고 참조는 없다.)

    깊은복사는 복사하는 객체, 또는 그 객체의 객체까지 모두 "완전히" 복사해버림

    참조도 물론 없어서 복사한뒤

    각각의 값을 변형시켜도 서로에게 영향을 미치지 않는다.

     

    깊은 복사하는 방법을 알아보자

     

    1) JSON 객체 이용

     

     

    2) 반복문 이용

     

     

    3) 메서드 이용

     

    출처: https://mightyotter.tistory.com/13 [Patience is a virtue:티스토리]

Designed by Tistory.