JavaScript如何深度复制一个包含嵌套对象、数组和函数的数组?

3

我有一个结构类似于这样的数组,并且我想要获取它的副本(以便修改并用于React setState())。在Python中,我可以使用copy.deepcopy(),但是我找不到JavaScript中简单的方法。

notes=[
        {
          contents: "Hello World 1",
          function: console.log,
          children: [
            {
              contents: "Hello World A",
              function: console.log,
              children: []
            },
          ]
        },
        {
          contents: "Hello World 2",
          function: console.log,
          children: []
        }
      ]

我在stackoverflow上找到了类似的解决方案,但它们都不适用于我。 https://medium.com/@Farzad_YZ/3-ways-to-clone-objects-in-javascript-f752d148054d 两种方法只是浅拷贝,而JSON.parse无法处理函数。
我想要一个函数,可以深度复制任何包含任意嵌套JavaScript数据类型结构的数组或对象。
我不想重新发明轮子,编写一个复杂的递归函数来遍历和克隆所有内容,是否有现成的解决方案?
3个回答

5

编辑- 您可以使用下面的解决方案,或者只需导入Lodash并使用此https://lodash.com/docs/#cloneDeep


我用我找到的解决方案回答自己的问题。有人在我链接的文章的评论部分发布了这个,它似乎可以工作。

notes=[
        {
          contents: "Hello World 1",
          function: console.log,
          children: [
            {
              contents: "Hello World A",
              function: console.log,
              children: []
            },
          ]
        },
        {
          contents: "Hello World 2",
          function: console.log,
          children: []
        }
      ]

function deepCopy(src) {
  let target = Array.isArray(src) ? [] : {};
  for (let key in src) {
    let v = src[key];
    if (v) {
      if (typeof v === "object") {
        target[key] = deepCopy(v);
      } else {
        target[key] = v;
      }
    } else {
      target[key] = v;
    }
  }

  return target;
}

看我的答案...一行解决方案... const copy = notes.map(a => ({ ...a })); - SakoBu
@hev1 你是说它不能克隆函数吗?我这边可以正常工作 https://www.screencast.com/t/WWaBe9Rloe - pyjamas

2

如果找不到更好的答案,最简单的方法是:

var note2 = JSON.parse(JSON.stringify(notes))

但是它没有复制函数,所以请检查。
function iterationCopy(src) {
  let target = {};
  for (let prop in src) {
    if (src.hasOwnProperty(prop)) {
      target[prop] = src[prop];
    }
  }
  return target;
}
const source = {a:1, b:2, c:3};
const target = iterationCopy(source);
console.log(target); // {a:1, b:2, c:3}
// Check if clones it and not changing it
source.a = 'a';
console.log(source.a); // 'a'
console.log(target.a); // 1

and

function bestCopyEver(src) {
  return Object.assign({}, src);
}
const source = {a:1, b:2, c:3};
const target = bestCopyEver(source);
console.log(target); // {a:1, b:2, c:3}
// Check if clones it and not changing it
source.a = 'a';
console.log(source.a); // 'a'
console.log(target.a); // 1

来自使用迭代进行深拷贝


0

你应该使用for循环进行迭代并判断项类型,当它是对象类型时,使用递归。函数类似于:

function copy(obj1, obj2) {
  var obj2=obj2||{}; 
  for(var name in obj1) {
    if(typeof obj1[name] === "object") { 
      obj2[name]= (obj1[name].constructor===Array)?[]:{}; 
      copy(obj1[name],obj2[name]);
     } else {
      obj2[name]=obj1[name]; 
   }
 }
  return obj2; 
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接