资讯专栏INFORMATION COLUMN

克隆

freecode / 1893人阅读

摘要:结构化算法优于的地方优于的地方结构化克隆可以复制对象。的克隆粒度将会跟原始对象相同,并且复制出来相同的像素数据。企图去克隆节点同样会抛出异常。消息通道的传递是异步的,使用结构化克隆算法。

JavaScript 深拷贝性能分析(汉化版)
JavaScript 深拷贝性能分析

Object.assign()

Object.assign 方法只会拷贝源对象自身的并且可枚举的属性到目标对象。该方法使用源对象的[[Get]]和目标对象的[[Set]],所以它会调用相关 getter 和 setter。

JSON.parse

过去浏览器内部传递的对象是使用JSON进行序列化的。 现代浏览器序列化将使用结构化克隆算法。这将会使更多对象可以被安全的传递。

JSON parse的优缺点

优点

代码简单

const obj = /* ... */
const copy = JSON.parse(JSON.stringify(obj))

缺点

如果对象复杂,你可能创建一个临时的,很大的字符串,只是为了把它重新放回解析器。

无法解决处理循环对象, 如当您构建树状数据结构,其中一个节点引用其父级,而父级又引用其子级。

const x = {};
const y = {x};
x.y = y; // Cycle: x.y.x.y.x.y.x.y.x...
const copy = JSON.parse(JSON.stringify(x)); // throws!

诸如 Map, Set, RegExp, Date, ArrayBuffer 和其他内置类型在进行序列化时会丢失

结构化克隆算法

因为它支持包含循环图的对象的序列化 ---对象可以引用在同一个图中引用其他对象的对象。此外,在某些情况下,结构化克隆算法可能比JSON更高效。
结构化算法优于JSON的地方

优于 JSON 的地方

结构化克隆可以复制 RegExp 对象。

结构化克隆可以复制 Blob、File 以及 FileList 对象。

结构化克隆可以复制 ImageData 对象。CanvasPixelArray

的克隆粒度将会跟原始对象相同,并且复制出来相同的像素数据。

结构化克隆可以正确的复制有循环引用的对象

结构化克隆所不能做到的

Error 以及 Function 对象是不能被结构化克隆算法复制的;如果你尝试这样子去做,这会导致抛出 DATA_CLONE_ERR 的异常。

企图去克隆 DOM 节点同样会抛出 DATA_CLONE_ERROR 异常。

对象的某些特定参数也不会被保留

RegExp 对象的 lastIndex 字段不会被保留

属性描述符,setters 以及 getters(以及其他类似元数据的功能)同样不会被复制。例如,如果一个对象用属性描述符标记为 read-only,它将会被复制为 read-write,因为这是默认的情况下。

原形链上的属性也不会被追踪以及复制。

symbols 不会被复制

MessageChannel

Channel Messaging API的Channel Messaging接口允许我们创建一个新的消息通道,并通过它的两个MessagePort 属性发送数据。

消息通道的传递是异步的,使用结构化克隆算法。

Note: 此特性在 Web Worker 中可用。
兼容性如下:

History API

HTML5引入了 history.pushState()history.replaceState() 方法,它们分别可以添加和修改历史记录条目。这些方法通常与window.onpopstate 配合使用。

pushState
history.pushState(data({a: "hi"}), name("tdy"), url("bar.html"))
改变浏览器的url显示,但是浏览器本身不会去做任何的改变。

history.replaceState() 参数和pushState一致,修改当前页面的信息

window.onpopstate
调用history.pushState()或者history.replaceState()不会触发popstate事件. popstate事件只会在浏览器某些行为下触发, 比如点击后退、前进按钮(或者在JavaScript中调用history.back()、history.forward()、history.go()方法).信息保存在state属性上

pushState或replaceState时需要复制一份状态对象,这个状态对象使用结构化克隆而且是同步的
最大储存对象大小为640KB。

Safari 浏览器对replaceState调用的限制数量为 30 秒内 100 次
兼容性如下:

Notification API

简洁明了

function structuralClone(obj) {
  return new Notification("", {data: obj, silent: true}).data
}

const obj = /* ... */
const clone = structuralClone(obj)

兼容性欠佳,并且,Safari 总是返回undefined。

最后

如果您没有循环对象,并且不需要保留内置类型,则可以使用跨浏览器的JSON.parse(JSON.stringify())获得最快的克隆性能。

如果你想要一个适当的结构化克隆,MessageChannel是你唯一可靠的跨浏览器的选择。

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/107252.html

相关文章

  • js克隆一个对象,支持循环引用的克隆

    摘要:判断参数是否为待判断的参数克隆一个对象要克隆的目标对象克隆节点,绑定事件的有问题,暂不处理克隆在当前作用域,在全局克隆其它对象,通过识别复制后的对象与原对象是否相同来决定传不传参数,像数组是不能传参数的使用防止对象重写了方法支持节点克隆 (function(){ var toString=Object.prototype.toString,gObj={},cloneHelper=f...

    fai1017 评论0 收藏0
  • Java实现对象克隆的方法

    摘要:优点简单易实现缺点无法真正克隆对象深克隆实现通过递归克隆实现代码输出通过序列化实现代码输出结果分析采用深克隆能有效隔离源对象与克隆对象的联系。 本文首发于cartoon的博客     转载请注明出处:https://cartoonyu.github.io/cartoon-blog/post/java/java%E5%AE%9E%E7%8E%B0%E5%85%8B%E9%9A%86%E...

    zhoutk 评论0 收藏0
  • jQuery源码解析之clone()

    摘要:五作用的关键方法,用来从目标节点克隆数据添加事件给克隆的元素注意采用数据分离的方法来保存上的事件和数据,利用标记每个元素,然后在内存上,将每个元素相关的数据放到内存中,然后在和内存的数据之间建立映射。 showImg(https://segmentfault.com/img/remote/1460000018991125); 前言:这篇讲完后,jQuery的文档处理就告一段落了,有空我...

    coolpail 评论0 收藏0
  • JavaScript对象克隆

    摘要:原始类型对象指的是字符串数值布尔值,引用类型对象指的是数组对象函数。既然对象分为这两类,他们的复制克隆也是有差别的。总结根据上面的情况,另外,克隆引用对象必须采用完整克隆深度克隆,包括对象的值也是一个对象也要进行完整克隆深度克隆。 前言 之前有人问我如何克隆一个JS对象,我当时没答上来;过后我查资料弄懂了这个问题,现在整理成文。 正文 JavaScript的一切实例都是对象,但他们也分...

    douzifly 评论0 收藏0
  • 【转】JavaScript 对象的深度克隆

    摘要:在聊以下简称深度克隆之前,我们先来了解一下中对象的组成。克隆或者拷贝分为种浅度克隆深度克隆。浅度克隆基本类型为值传递,对象仍为引用传递。 该文转载自http://www.cnblogs.com/zichi/p/4568150.html,有部分修改。 在聊JavaScript(以下简称js)深度克隆之前,我们先来了解一下js中对象的组成。在 js 中一切实例皆是对象,具体分为 原始类型 ...

    JowayYoung 评论0 收藏0

发表评论

0条评论

最新活动
阅读需要支付1元查看
<