javaScript自带的深拷贝

  

通过引用调用(引用调用)

译注:通过引用调用可能有点绕,你就当做“用引用作为参数调用”。

JavaScript通过引用传递所有的东西。如果你不知道这句话的意思,那么看下这个例子:

功能变异(obj) {
  obj。=true;
  }
  const obj={:假};
  变异(obj)
  console.log (obj.a);//正确的
  复制代码

函数变异更改了作为参数传递的对象。在“通过值调用(调用的值)”的环境中,函数会得到传递过来的值,也就是一个拷贝,这个函数使用这个值来一起工作。函数对对象所做的任何更改在该函数之外都不可见。但是在像JavaScript这样的“通过引用调用“环境中,函数会得到一个——你已经猜到了———并会改变实际对象本身。因此最后的控制台。日志会打印出真实的。

但是在有些时候,你可能想保持你的原始对象并且为对应的函数创建一个副本。

译:对于这个还不是很了解的朋友可以看下在下的相关资源

<李>

你不知道Js - types&格拉默——cp2值

<李>

原始类型和引用类型的区别

浅拷贝:Object.assign ()

拷贝一个对象的一种办法是使用对象。分配(目标,来源…)。他接受任意数量的源对象,枚举他们自己所有的属性并将这些属性分配给目标。如果我们用一个新的空的对象作为目标,我们基本上是在进行拷贝。

 const obj=/*……*/;
  const复制=对象。分配({},obj);
  复制代码

然而,这是一个拷贝。如果我们的对象包含一个对象,那他们将会保持共享引用,这不是我们想要的结果:

函数mutateDeepObject (obj) {
  obj.a。一件=true;
  }
  const obj={:{:假}};
  const复制=对象。分配({},obj);
  mutateDeepObject(复制)
  console.log (obj.a.thing);//正确的
  复制代码

另一个潜在的是Object.assign()将getter转换为一个单纯的属性。

译:和getter有什么关系?来试试:

 var myObject={
  会说(){
  返回“嗨,xiaohesong”;
  }
  };
  控制台。日志(分配之前,对象。getOwnPropertyDescriptor (myObject, '说'))
  var obj=对象。myObject分配({})
  控制台。日志(分配后,对象。getOwnPropertyDescriptor (obj, '说'));
  复制代码

动手试试,是不是变成了单纯的属性吗?那再动手试试setter呗?

那么现在呢?事实证明,有两种办法可以创建对象的拷贝。

注意:有人询问关于对象拓展运算符。其实对象拓展也是创建了一个浅拷贝。

译:关于拓展运算符,可以看看在下之前介绍的几个特性。

JSON。解析

有个最古老的方法去创建对象拷贝的是将对象转换为字符串表示形式,然后再将他解析回对象的形式。这个感觉有些沉重,但是确实可以有效:

 const obj=/*……*/;
  const复制=JSON.parse (JSON.stringify (obj));
  复制代码

这里有个缺点就是你创建了一个临时的而且可能会很大的字符串,其目的只是为了转回到解析器。另一个缺点是这种方法不能处理循环对象。不管你怎么认为,这些都很容易发生,例如,在构建树状数据结构时,节点引用其父节点,而父节点又引用其子节点。

 const x={};
  const y={x};
  x。y=y;//循环:x.y.x.y.x.y.x.y.x……
  const复制=JSON.parse (JSON.stringify (x));//把!
  复制代码

此外,像地图,集,regexp,日期,ArrayBuffers和其他内置类型这样的东西在序列化时会丢失。

译:对JSON。stringify不了解的朋友,可以看看你不知道Js:类型,语法cp4:强迫JSON Stringification。

结构化克隆

结构化克隆是一种现有的算法,用于将值从一个领域转移到另一个领域,例如,当你调用postMessage将消息发送到另一个窗口(窗口)或网络系统时,就会使用此方法。结构化克隆的好处是它可以处理循环对象并支持大量的内置类型。问题在于,在编写本文时,算法不会直接暴露,只能作为其他API的一部分,所以我们必须先看看那些API,不是吗…

MessageChannel

正如我所说,无论何时调用postMessage,都会使用结构化克隆算法(译:在针对对象的时候,是这种情况)。我们可以创建一个MessageChannel并发送一条消息。在接收端,消息包含原始数据对象的结构克隆.

函数structuralClone (obj) {
  返回新的承诺(解决=比;{
  const{端口1,端口2}=new MessageChannel ();
  端口2。onmessage=ev=比;解决(ev.data);
  port1.postMessage (obj);
  });
  }
  const obj=/*……*/;
  const克?等待structuralClone (obj);
  复制代码

javaScript自带的深拷贝