JavaScript에서 객체 복사


대본:

컴포넌트 사이에 객체를 소품이나 함수의 인수로 전달할 때마다 원래 객체에 영향을 미치지 않도록 해당 객체를 복사해야 합니다. 이제 필요에 따라 복사된 개체를 쉽게 변경할 수 있습니다.

따라서 다음은 그렇게 하는 데 사용할 수 있는 방법입니다.
  • 스프레드 연산자
  • Object.assign
  • JSON.parse 및 JSON.stringify

  • 이러한 방법을 사용하면 개체가 완전히 복사됩니까? 중첩된 개체도 복사합니까?

    다른 예를 살펴보겠습니다.

    let deepObj = {a: 4: b: {name: 'react'}, d: {name: 'angular'}};
    


    따라서 deepObj는 중첩된 객체이며 중첩된 객체, 즉 참조로 값이 있는 객체를 복사할 때 얕은 복사와 깊은 복사의 개념이 있습니다.
  • 얕은 복사: 값 중 하나라도 참조 유형인 경우 한 수준만 복사합니다. 참조를 복사하지만 정확한 값은 새 개체에 복사되지 않습니다.
  • 전체 복사: 위의 deepObj 개체가 있는 예제와 같은 참조 유형인 경우에도 중첩 값의 모든 수준을 복사합니다.

  • 개체를 복사해 보겠습니다.



    1. 스프레드 연산자 및 Object.assign():

    예 1:

    let obj1 = {a: 3, b: 4, c: "react"}, copiedObj1 = {};
    
    copiedObj1 = {...obj1};
    copiedObj1.c = "angular";
    
    console.log(copiedObj1, obj1); 
    {a: 3, b: 4, c: "angular"}
    {a: 3, b: 4, c: "react"}
    
    
    
    let obj2 = {a: 3, b: 4, c: "react"}, copiedObj2 = {};
    
    copiedObj2 = Object.assign({}, obj2);
    copiedObj2.c = "vue";
    
    console.log(copiedObj2, obj2); 
    {a: 3, b: 4, c: "vue"}
    {a: 3, b: 4, c: "react"}
    


    개체 값에 참조 유형이 없고 복사된 개체에 영향을 주지 않는 속성을 변경하려고 하면 둘 다 개체를 완벽하게 복사합니다.

    예2:

    let obj1 = {a: 3, c: [1,2]}, newObj1 = {};
    newObj1 = {...obj1};
    newObj1.c.push(5);
    
    console.log(newobj1, obj1); 
    {a: 3, c: [1,2,5]} 
    {a: 3, c: [1,2,5]}
    
    
    let obj2 = {a: 3, c: [1,2]}, newObj2 = {};
    newObj2 = Object.assign({}, obj2);
    newObj2.c.push(5);
    
    console.log(newobj2, obj2); 
    {a: 3, c: [1,2,5]}
    {a: 3, c: [1,2,5]}
    


    여기서 속성 c 값은 두 객체 모두에서 [1,2,5]로 변경되므로 참조 유형, 즉 배열([1,2]) 때문에 완벽하게 복사되지 않습니다. 배열에 대한 참조를 복사합니다. 따라서 Spread operator and Object.assign() only does shallow copying not deep copying.
    2. JSON.parse() 및 JSON.stringify():

    var obj1 = {a: 3, b: 4, c: "react"};
    var copiedObj1 = JSON.parse(JSON.stringify(obj1));
    copiedObj1.c = "node";
    
    console.log(copiedObj1, obj1); 
    {a: 3, b: 4, c: "node"}
    {a: 3, b: 4, c: "react"}
    
    
    var obj2 = {a: 3, c: [1,2]};
    var copiedObj2 = JSON.parse(JSON.stringify(obj2));
    copiedObj2.c.push(5);
    
    console.log(copiedObj2 , obj2);
    {a: 3, c: [1,2,5]} 
    {a: 3, c: [1,2]}
    


    이것은 두 경우 모두 복사된 개체의 변경 사항이 원본 개체에 영향을 미치지 않으므로 개체를 완벽하게 복사합니다.

    But this works only in those cases where value is converted to string first and it gets parsed again.
    Following are few of the cases where it fails to copy the object.



    let obj = {
      name: 'laptop',
      value: function () {
        return 100000';
      }
    }
    
    let copiedObj = JSON.parse(JSON.stringify(obj));
    
    console.log(copiedObj);
    {name: 'laptop'}
    


    실패 -> 복사된 개체에서 값 메서드를 제거했습니다.

    let obj = {a: undefined, b: new Date()}
    
    let copiedObj = JSON.parse(JSON.stringify(obj));
    
    console.log(copiedObj);
    {b: "2020-06-06T16:23:43.910Z"}
    


    실패 -> 첫 번째 속성을 제거하고 날짜 값을 문자열로 변환했습니다.


    얕은 복사용


  • 스프레드 연산자
  • Object.assign().

  • 딥 카피용


  • lodash 라이브러리 사용cloneDeep 메서드(_.cloneDeep(중첩된 개체))
  • 하나의 경우만 다루는 아래 예제와 같이 참조 유형을 처리할 사용자 정의 함수를 만드십시오.

  • function deepCopy(obj) {
        let copiedObj = {};
        for(key in obj) {
            if(Array.isArray(obj[key])) {
                copiedObj[key] = [...obj[key]];
            } else {
                copiedObj[key] = obj[key]
            }
        }
        return copiedObj;
    }
    
    var obj = {value1: 5, value2: [1,2,3]};
    
    var copiedObj = deepCopy(obj);
    copiedObj.value2.push(5);
    
    console.log(copiedObj , obj);
    {value1: 5, value2: [1,2,3,5]}
    {value1: 5, value2: [1,2,3]}
    


    Better way will be to use recursion to handle reference type



    따라서 더 많은 계산이 필요하거나 사용자 정의 함수를 만들고 더 많은 경우를 추가할 수 있으므로 딥 클로닝을 수행할 수 있는 우수한 성능 이벤트를 제공하는 다른 라이브러리가 있습니다.

    결론: 전달되는 개체의 참조 유형인 경우 항상 값을 확인하십시오. 그리고 얕고 깊은 복사를 더 잘 사용하십시오.

    읽어 주셔서 감사합니다!

    좋은 웹페이지 즐겨찾기