관리 메뉴

Bbaktaeho

[Javascript] 얕은 복사, 깊은 복사 (배열 복사, 객체 복사, shallow copy, deep copy, slice, JSON.parse, JSON.stringify) 본문

프로그래밍 (Programming)/자바스크립트 (JavaScript)

[Javascript] 얕은 복사, 깊은 복사 (배열 복사, 객체 복사, shallow copy, deep copy, slice, JSON.parse, JSON.stringify)

Bbaktaeho 2020. 3. 30. 16:40
반응형

📚 복사

  • 먼저 복사란, 원본과 모두 같은 내용으로 사본을 만드는 작업
  • 원본은 따로 존재하고 사본도 따로 존재하게, 즉 원본과 사본은 내용은 같지만 서로 다르게 존재하고 있다는 뜻임

📗 얕은 복사

사본을 만들어내지 않고 원본을 참조하도록 복사한 척을 하는 것

  • 기본형에서 얕은 복사
    기본형 타입에서 복사한 데이터를 변경할 때 원본도 같이 변경되는 일은 발생하지 않는다.

    var v1 = "test";
    var v2 = v1; // (1)
    
    console.log(v1);
    console.log(v2);
    
    v2 = "hi taeho"; // (2)
    
    console.log(v1);
    console.log(v2);
    test
    test
    test
    hi taeho

    주석(1) 코드에서 메모리 변화

    두 변수는 서로 같은 주솟값을 참조하고 있음

    주석(2) 코드에서 메모리 변화

    원본의 주소를 참조하고 있었지만 새로운 데이터로 변경할 때 데이터 영역에서 새로운 데이터를 할당하고 그 주솟값을 다시 참조함
  • 참조형에서 얕은 복사

    var arr1 = [1, 2, 3, 4];
    var arr2 = arr1; // (1)
    
    console.log(arr1);
    console.log(arr2);
    
    arr2[0] = 0; // (2)
    
    console.log(arr1);
    console.log(arr2);
    [ 1, 2, 3, 4 ]
    [ 1, 2, 3, 4 ]
    [ 0, 2, 3, 4 ]
    [ 0, 2, 3, 4 ]

    주석(1) 코드에서 메모리 변화

    두 변수는 서로 같은 주솟값을 참조하고 있음

    주석(2) 코드에서 메모리 변화

    arr2 가 arr1 과 같은 배열을 참조하고 있기 때문에 사본인 arr2 에서 배열의 요소를 수정했을 때 원본에도 수정이 일어남. 즉, 원본을 가리키는 또 다른 식별자가 생겨난 것임(얕은 복사)

📒 깊은 복사

완벽하게 원본과 사본을 나눠 복사하는 방법

  • 배열의 복사 (깊은 복사같은 얕은 복사)
    Array.prototype.slice() 를 사용하면 새로운 배열을 반환해준다. (참조형 요소가 있다면 얕은 복사)

    var arr1 = [1, 2, 3, 4];
    var arr2 = arr1.slice();
    
    console.log("arr1: ", arr1);
    console.log("arr2: ", arr2);
    
    arr2[0] = 0;
    
    console.log("arr1: ", arr1);
    console.log("arr2: ", arr2);
    
    console.log(arr1 === arr2);
    arr1:  [ 1, 2, 3, 4 ]
    arr2:  [ 1, 2, 3, 4 ]
    arr1:  [ 1, 2, 3, 4 ]
    arr2:  [ 0, 2, 3, 4 ]
    false
  • 객체의 깊은 복사
    객체에 따른 사용자 정의 함수를 만들어 복사할 수 있다.

    function deepCopy(o) {
      var result = {};
      if (typeof o === "object" && o !== null)
        for (i in o) result[i] = deepCopy(o[i]);
      else result = o;
      return result;
    }
    var obj1 = {
      a: 1,
      b: [1, 2, 3]
    };
    
    var obj2 = deepCopy(obj1);
    
    console.log(obj1 === obj2);
    console.log(obj1);
    console.log(obj2);
    false
    { a: 1, b: [ 1, 2, 3 ] }
    { a: 1, b: { '0': 1, '1': 2, '2': 3 } }
  • JSON.parse, JSON.stringify 로 복사
    깊은 복사는 가능하지만 gettser/setter 등 JSON 으로 변경할 수 없는 프로퍼티는 무시한다. 배열도 깊은 복사가 가능하지만 배열 관련 함수는 사용 불가능하다.

    var obj1 = {
      a: "hello",
      b: [1, 2, 3],
      c: { cc: "left" }
    };
    
    var obj2 = JSON.parse(JSON.stringify(obj1));
    
    console.log(obj1);
    console.log(obj2);
    console.log(obj1 === obj2);
    
    obj2.c.cc = "right";
    
    console.log(obj1);
    console.log(obj2);
    { a: 'hello', b: [ 1, 2, 3 ], c: { cc: 'left' } }
    { a: 'hello', b: [ 1, 2, 3 ], c: { cc: 'left' } }
    false
    { a: 'hello', b: [ 1, 2, 3 ], c: { cc: 'left' } }
    { a: 'hello', b: [ 1, 2, 3 ], c: { cc: 'right' } }

반응형