.jpg)
网友问题:
克隆 JavaScript 对象的最有效方法是什么?我已经看到有人使用,但这是非标准的,只有Firefox支持。obj = eval(uneval(o));
我做过这样的事情,但质疑效率。obj = JSON.parse(JSON.stringify(o));
我还看到了具有各种缺陷的递归复制函数。
我很惊讶没有规范的解决方案存在。

网友回答:
查看此基准测试:http://jsben.ch/#/bWfk9
在我之前的测试中,速度是我发现的主要问题
JSON.parse(JSON.stringify(obj))
是深度克隆对象的最慢方法(它比 jQuery.extend 慢,标志设置为 true 10-20%)。deep
jQuery.extend 在标志设置为(浅克隆)时非常快。这是一个不错的选择,因为它包含一些用于类型验证的额外逻辑,并且不会复制未定义的属性等,但这也会减慢您的速度。deepfalse
如果你知道你试图克隆的对象的结构,或者可以避免深度嵌套数组,你可以编写一个简单的循环来克隆你的对象,同时检查hasOwnProperty,它将比jQuery快得多。for (var i in obj)
最后,如果您尝试在热循环中克隆已知的对象结构,则只需内联克隆过程并手动构造对象即可获得更高的性能。
JavaScript 跟踪引擎在优化循环方面很糟糕,检查 hasOwnProperty 也会减慢你的速度。当速度是绝对必要的时,手动克隆。for..in
var clonedObject = {
knownProp: obj.knownProp,
..
}
当心在对象上使用该方法 – 返回 ISO 格式的日期字符串表示形式,不会转换回对象。有关更多详细信息,请参阅此答案。JSON.parse(JSON.stringify(obj))DateJSON.stringify(new Date())JSON.parse()Date
此外,请注意,至少在Chrome 65中,本机克隆不是要走的路。根据JSPerf的说法,通过创建新函数来执行本机克隆比使用JSON.stringify慢近800倍,JSON.stringify在整个方面都非常快。
ES6 更新
如果您使用的是 Javascript ES6,请尝试使用此本机方法进行克隆或浅拷贝。
Object.assign({}, obj);

网友回答:
现在有一个名为“结构化克隆”的JS标准,它在Node 11及更高版本中实验性地工作,将登陆浏览器,并且具有现有系统的polyfill。
structuredClone(value)
如果需要,请先加载填充代码:
import structuredClone from '@ungap/structured-clone';
有关更多详细信息,请参阅此答案。
如果你在对象中不使用s、functions、、、RegExps、Maps、Sets、Blob、FileLists、ImageDatas、稀疏数组、Typed Arrays或其他复杂类型,那么一个非常简单的深层克隆对象的行是:DateundefinedInfinity
JSON.parse(JSON.stringify(object))
const a = {
string: 'string',
number: 123,
bool: false,
nul: null,
date: new Date(), // stringified
undef: undefined, // lost
inf: Infinity, // forced to 'null'
re: /.*/, // lost
}
console.log(a);
console.log(typeof a.date); // Date object
const clone = JSON.parse(JSON.stringify(a));
console.log(clone);
console.log(typeof clone.date); // result of .toISOString()
请参阅 Corban 的基准测试答案。
由于克隆对象不是简单的(复杂类型、循环引用、函数等),因此大多数主要库都提供克隆对象的函数。不要重新发明轮子 – 如果您已经在使用库,请检查它是否具有对象克隆功能。例如
cloneDeepangular.copyjQuery.extend(true, { }, oldObject).clone()just-clone
网友回答:
2022 年更新:全局函数已经在Firefox 94,Node 17和Deno 1.14中可用。structuredClone
HTML 标准包括一个内部结构化克隆/序列化算法,可以创建对象的深度克隆。它仍然仅限于某些内置类型,但除了 JSON 支持的少数类型之外,它还支持日期、正则表达式、映射、集、blob、文件列表、图像数据、稀疏数组、类型数组,以及将来可能更多。它还保留克隆数据中的引用,允许它支持会导致 JSON 错误的循环和递归结构。
全局函数由节点 17.0 提供:structuredClone
const clone = structuredClone(original);
以前的版本:Node.js 中的模块(从 Node 11 开始)直接公开结构化序列化 API,但此功能仍标记为“实验性”,并且在将来的版本中可能会更改或删除。如果您使用的是兼容版本,则克隆对象非常简单:v8
const v8 = require('v8');
const structuredClone = obj => {
return v8.deserialize(v8.serialize(obj));
};
全局函数将很快由所有主流浏览器提供(之前在 GitHub 上的 whatwg/html#793 中讨论过)。它看起来/将看起来像这样:structuredClone
const clone = structuredClone(original);
在发布之前,浏览器的结构化克隆实现只会间接公开。
使用现有 API 创建结构化克隆的开销较低的方法是通过 MessageChannel 的一个端口发布数据。另一个端口将发出一个事件,其中包含附加的结构化克隆。遗憾的是,侦听这些事件必然是异步的,同步替代方案不太实用。message.data
class StructuredCloner {
constructor() {
this.pendingClones_ = new Map();
this.nextKey_ = 0;
const channel = new MessageChannel();
this.inPort_ = channel.port1;
this.outPort_ = channel.port2;
this.outPort_.onmessage = ({data: {key, value}}) => {
const resolve = this.pendingClones_.get(key);
resolve(value);
this.pendingClones_.delete(key);
};
this.outPort_.start();
}
cloneAsync(value) {
return new Promise(resolve => {
const key = this.nextKey_++;
this.pendingClones_.set(key, resolve);
this.inPort_.postMessage({key, value});
});
}
}
const structuredCloneAsync = window.structuredCloneAsync =
StructuredCloner.prototype.cloneAsync.bind(new StructuredCloner);
const main = async () => {
const original = { date: new Date(), number: Math.random() };
original.self = original;
const clone = await structuredCloneAsync(original);
// They're different objects:
console.assert(original !== clone);
console.assert(original.date !== clone.date);
// They're cyclical:
console.assert(original.self === original);
console.assert(clone.self === clone);
// They contain equivalent values:
console.assert(original.number === clone.number);
console.assert(Number(original.date) === Number(clone.date));
console.log("Assertions complete.");
};
main();
同步创建结构化克隆没有好的选择。这里有一些不切实际的技巧。
history.pushState()并且两者都创建其第一个参数的结构化克隆,并将该值分配给 .您可以使用它来创建任何对象的结构化克隆,如下所示:history.replaceState()history.state
const structuredClone = obj => {
const oldState = history.state;
history.replaceState(obj, null);
const clonedObj = history.state;
history.replaceState(oldState, null);
return clonedObj;
};
'use strict';
const main = () => {
const original = { date: new Date(), number: Math.random() };
original.self = original;
const clone = structuredClone(original);
// They're different objects:
console.assert(original !== clone);
console.assert(original.date !== clone.date);
// They're cyclical:
console.assert(original.self === original);
console.assert(clone.self === clone);
// They contain equivalent values:
console.assert(original.number === clone.number);
console.assert(Number(original.date) === Number(clone.date));
console.log("Assertions complete.");
};
const structuredClone = obj => {
const oldState = history.state;
history.replaceState(obj, null);
const clonedObj = history.state;
history.replaceState(oldState, null);
return clonedObj;
};
main();
虽然是同步的,但这可能非常慢。它会产生与操作浏览器历史记录相关的所有开销。重复调用此方法可能会导致 Chrome 暂时无响应。
构造函数创建其关联数据的结构化克隆。它还会尝试向用户显示浏览器通知,但除非您已请求通知权限,否则这将以静默方式失败。如果您拥有用于其他目的的权限,我们将立即关闭我们创建的通知。Notification
const structuredClone = obj => {
const n = new Notification('', {data: obj, silent: true});
n.onshow = n.close.bind(n);
return n.data;
};
'use strict';
const main = () => {
const original = { date: new Date(), number: Math.random() };
original.self = original;
const clone = structuredClone(original);
// They're different objects:
console.assert(original !== clone);
console.assert(original.date !== clone.date);
// They're cyclical:
console.assert(original.self === original);
console.assert(clone.self === clone);
// They contain equivalent values:
console.assert(original.number === clone.number);
console.assert(Number(original.date) === Number(clone.date));
console.log("Assertions complete.");
};
const structuredClone = obj => {
const n = new Notification('', {data: obj, silent: true});
n.close();
return n.data;
};
main();
模板简介:该模板名称为【复制克隆 JavaScript 对象的最有效方法是什么?obj = JSON.parse(JSON.stringify(o));】,大小是暂无信息,文档格式为.编程语言,推荐使用Sublime/Dreamweaver/HBuilder打开,作品中的图片,文字等数据均可修改,图片请在作品中选中图片替换即可,文字修改直接点击文字修改即可,您也可以新增或修改作品中的内容,该模板来自用户分享,如有侵权行为请联系网站客服处理。欢迎来懒人模板【JavaScript】栏目查找您需要的精美模板。