克隆 JavaScript 对象的最有效方法是什么?我见过 obj = eval(uneval(o));
正在使用,但这 是非标准的,仅受 Firefox 支持。
我已经完成了 obj = JSON.parse(JSON.stringify(o));
类的事情。但质疑效率。
我还看到了具有各种缺陷的递归复制函数。
我很惊讶不存在规范的解决方案。
原文由 jschrab 发布,翻译遵循 CC BY-SA 4.0 许可协议
克隆 JavaScript 对象的最有效方法是什么?我见过 obj = eval(uneval(o));
正在使用,但这 是非标准的,仅受 Firefox 支持。
我已经完成了 obj = JSON.parse(JSON.stringify(o));
类的事情。但质疑效率。
我还看到了具有各种缺陷的递归复制函数。
我很惊讶不存在规范的解决方案。
原文由 jschrab 发布,翻译遵循 CC BY-SA 4.0 许可协议
检查这个基准:http: //jsben.ch/#/bWfk9
在我之前的测试中,速度是我发现的主要问题
JSON.parse(JSON.stringify(obj))
是深度克隆对象的最慢方法(它比 jQuery.extend with deep
flag set true 慢 10-20%)。
当 deep
标志设置为 false
(浅克隆)时,jQuery.extend 非常快。这是一个不错的选择,因为它包含一些用于类型验证的额外逻辑并且不会复制未定义的属性等,但这也会让您的速度变慢一点。
如果你知道你试图克隆的对象的结构或者可以避免深层嵌套数组,你可以编写一个简单的 for (var i in obj)
循环来克隆你的对象,同时检查 hasOwnProperty,它会比 jQuery 快得多。
最后,如果您试图在热循环中克隆一个已知的对象结构,您可以通过简单地内联克隆过程并手动构造对象来获得更多的性能。
JavaScript 跟踪引擎在优化 for..in
循环和检查 hasOwnProperty 也会减慢你的速度。当绝对需要速度时手动克隆。
var clonedObject = {
knownProp: obj.knownProp,
..
}
Beware using the JSON.parse(JSON.stringify(obj))
method on Date
objects - JSON.stringify(new Date())
returns a string representation of the date in ISO format, which JSON.parse()
doesn’t 转换回 Date
对象。 有关详细信息,请参阅此答案。
此外,请注意,至少在 Chrome 65 中,本机克隆不是可行的方法。根据 JSPerf 的说法,通过创建新函数执行本机克隆比使用 JSON.stringify 慢近 800 倍,后者在所有方面都非常快。
如果您使用的是 Javascript ES6,请尝试使用此本机方法进行克隆或浅拷贝。
Object.assign({}, obj);
原文由 Corban Brook 发布,翻译遵循 CC BY-SA 4.0 许可协议
10 回答11.2k 阅读
6 回答3k 阅读
5 回答4.8k 阅读✓ 已解决
4 回答3.1k 阅读✓ 已解决
2 回答2.7k 阅读✓ 已解决
3 回答2.3k 阅读✓ 已解决
3 回答2.1k 阅读✓ 已解决
本机深度克隆
现在有一个称为 “结构化克隆” 的 JS 标准,它在 Node 11 及更高版本中实验性地工作,将登陆浏览器,并 为现有系统提供 polyfill 。
如果需要,首先加载 polyfill:
有关更多详细信息,请参阅 此答案。
较早的答案
快速克隆数据丢失 - JSON.parse/stringify
如果您不使用
Date
s、functions、undefined
、Infinity
、RegExps、Maps、Sets、Blobs、FileLists、ImageDatas、sparse Arrays、Typed Arrays 或其他复杂类型在您的对象中,一个非常简单的深度克隆对象的方法是:JSON.parse(JSON.stringify(object))
有关基准,请参阅 Corban 的答案。
使用库进行可靠克隆
由于克隆对象并非易事(复杂类型、循环引用、函数等),大多数主要库都提供了克隆对象的函数。 不要重新发明轮子- 如果您已经在使用库,请检查它是否具有对象克隆功能。例如,
cloneDeep
- 克隆深;可以通过 lodash.clonedeep 模块单独导入,如果您还没有使用提供深度克隆功能的库,这可能是您的最佳选择AngularJS -
angular.copy
jQuery -
jQuery.extend(true, { }, oldObject)
;.clone()
只克隆 DOM 元素只是库 -
just-clone
;零依赖 npm 模块库的一部分,它只做一件事。适合各种场合的无罪实用程序。