development

ES6에서 객체를 복제하는 좋은 방법입니까?

big-blog 2020. 7. 5. 07:38
반응형

ES6에서 객체를 복제하는 좋은 방법입니까?


"javascript clone object"에 대한 인터넷 검색은 정말 이상한 결과를 가져옵니다. 그중 일부는 절망적으로 구식이며 일부는 너무 복잡합니다.

let clone = {...original};

이것에 문제가 있습니까?


얕은 클로닝에 좋습니다 . 객체 스프레드는 ECMAScript를 2018의 표준입니다 .

딥 클로닝을 위해서는 다른 솔루션 이 필요합니다 .

const clone = {...original} 얕은 클론에

const newobj = {...original, prop: newOne} 원본에 다른 소품을 불변 ​​적으로 추가하고 새 객체로 저장합니다.


편집 :이 답변을 게시했을 때 {...obj}대부분의 브라우저에서 구문을 사용할 수 없었습니다. 요즘에는 IE 11을 지원 해야하는 경우가 아니라면 잘 사용해야합니다.

Object.assign을 사용하십시오.

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/assign

var obj = { a: 1 };
var copy = Object.assign({}, obj);
console.log(copy); // { a: 1 }

그러나 이것은 딥 클론을 만들지는 않습니다. 아직까지는 심층 복제 방법이 없습니다.

편집 : 의견에 언급 된 @Mike 'Pomax'Kamermans는 다음을 사용하여 간단한 객체 (예 : 프로토 타입, 함수 또는 순환 참조 없음)를 딥 복제 할 수 있습니다 JSON.parse(JSON.stringify(input))


json.parse (json.stringify (object))를 사용하지 않으려면 재귀 적으로 키-값 복사본을 만들 수 있습니다.

function copy(item){
  let result = null;
  if(!item) return result;
  if(Array.isArray(item)){
    result = [];
    item.forEach(element=>{
      result.push(copy(element));
    });
  }
  else if(item instanceof Object && !(item instanceof Function)){ 
    result = {};
    for(let key in item){
      if(key){
        result[key] = copy(item[key]);
      }
    }
  }
  return result || item;
}

그러나 가장 좋은 방법은 자체 복제본을 반환 할 수있는 클래스를 만드는 것입니다

class MyClass{
    data = null;
    constructor(values){ this.data = values }
    toString(){ console.log("MyClass: "+this.data.toString(;) }
    remove(id){ this.data = data.filter(d=>d.id!==id) }
    clone(){ return new MyClass(this.data) }
}

사용한 메소드가 Date 와 같은 데이터 유형과 관련된 오브젝트에서 제대로 작동하지 않으면 다음을 시도하십시오.

수입 _

import * as _ from 'lodash';

딥 클론 객체

myObjCopy = _.cloneDeep(myObj);

@marcel의 답변에 이어 복제 된 객체에서 일부 기능이 여전히 누락되었음을 발견했습니다. 예 :

function MyObject() {
  var methodAValue = null,
      methodBValue = null

  Object.defineProperty(this, "methodA", {
    get: function() { return methodAValue; },
    set: function(value) {
      methodAValue = value || {};
    },
    enumerable: true
  });

  Object.defineProperty(this, "methodB", {
    get: function() { return methodAValue; },
    set: function(value) {
      methodAValue = value || {};
    }
  });
}

where on MyObject I could clone methodA but methodB was excluded. This occurred because it is missing

enumerable: true

which meant it did not show up in

for(let key in item)

Instead I switched over to

Object.getOwnPropertyNames(item).forEach((key) => {
    ....
  });

which will include non-enumerable keys.

I also found that the prototype (proto) was not cloned. For that I ended up using

if (obj.__proto__) {
  copy.__proto__ = Object.assign(Object.create(Object.getPrototypeOf(obj)), obj);
}

PS: Frustrating that I could not find a built in function to do this.


We can do that with two way:
1- First create a new object and replicate the structure of the existing one by iterating 
 over its properties and copying them on the primitive level.

let user = {
     name: "John",
     age: 30
    };

    let clone = {}; // the new empty object

    // let's copy all user properties into it
    for (let key in user) {
      clone[key] = user[key];
    }

    // now clone is a fully independant clone
    clone.name = "Pete"; // changed the data in it

    alert( user.name ); // still John in the original object

2- Second we can use the method Object.assign for that 
    let user = { name: "John" };
    let permissions1 = { canView: true };
    let permissions2 = { canEdit: true };

    // copies all properties from permissions1 and permissions2 into user
    Object.assign(user, permissions1, permissions2);

  -Another example

    let user = {
      name: "John",
      age: 30
    };

    let clone = Object.assign({}, user);
It copies all properties of user into the empty object and returns it. Actually, the same as the loop, but shorter.

But Object.assign() not create a deep clone

let user = {
  name: "John",
  sizes: {
    height: 182,
    width: 50
  }
};

let clone = Object.assign({}, user);

alert( user.sizes === clone.sizes ); // true, same object

// user and clone share sizes
user.sizes.width++;       // change a property from one place
alert(clone.sizes.width); // 51, see the result from the other one

To fix that, we should use the cloning loop that examines each value of user[key] and, if it’s an object, then replicate its structure as well. That is called a “deep cloning”.

There’s a standard algorithm for deep cloning that handles the case above and more complex cases, called the Structured cloning algorithm. In order not to reinvent the wheel, we can use a working implementation of it from the JavaScript library lodash the method is called _.cloneDeep(obj).


All the methods above do not handle deep cloning of objects where it is nested to n levels. I did not check its performance over others but it is short and simple.

The first example below shows object cloning using Object.assign which clones just till first level.

var person = {
    name:'saksham',
    age:22,
    skills: {
        lang:'javascript',
        experience:5
    }
}

newPerson = Object.assign({},person);
newPerson.skills.lang = 'angular';
console.log(newPerson.skills.lang); //logs Angular

Using the below approach deep clones object

var person = {
    name:'saksham',
    age:22,
    skills: {
        lang:'javascript',
        experience:5
    }
}

anotherNewPerson = JSON.parse(JSON.stringify(person));
anotherNewPerson.skills.lang = 'angular';
console.log(person.skills.lang); //logs javascript

참고URL : https://stackoverflow.com/questions/39736397/is-this-a-good-way-to-clone-an-object-in-es6

반응형