什么是最有效的方式来克隆一个JavaScript对象?我已经看到obj = eval(uneval(o));被使用,但它是非标准的,仅支持Firefox.我做了事情,如obj = JSON.parse(JSON.stringify(o));但质疑效率。
当前回答
class Handler { static deepCopy (obj) { if (Object.prototype.toString.call(obj) === '[object Array]') { const result = []; for (let i = 0, len = obj.length; i < len; i++) { result[i] = Handler.deepCopy(obj[i]); } return result; } else if (Object.prototype.toString.call(obj) === '[object Object]') { const result = {}; for (let prop in obj) { result[prop] = Handler.deepCopy(obj[prop]); } return result; } return obj; } }
其他回答
structuredClone(value)
如有必要,先加载聚合物:
import structuredClone from '@ungap/structured-clone';
查看此答案更多详细信息
如果您不使用日期、功能、未定义、无限、RegExps、地图、集、博布、文件列表、图像数据、分布式列表、类型列表或其它复杂类型在您的对象中,那么一个非常简单的单一列表来深化对象是:
JSON.parse(JSON.stringify(对象) )
lodash - cloneDeep; 可以通过 lodash.clonedeep 模块单独进口,并且可能是您最好的选择,如果您已经不使用图书馆,提供深度克隆功能 AngularJS - angular.copy jQuery - jQuery.extend(真实, { }, oldObject);.clone() 只克隆 DOM 元素仅图书馆 - just-clone; 一部分图书馆的零依赖 npm 模块,只做一件事。
因为回归只是太昂贵的JavaScript,我发现的大多数答案是使用回归,而JSON方法将错过非JSON转换部分(功能等)。所以我做了一些研究,并发现这个拖拉机技术避免它。
/*
* Trampoline to avoid recursion in JavaScript, see:
* https://www.integralist.co.uk/posts/functional-recursive-javascript-programming/
*/
function trampoline() {
var func = arguments[0];
var args = [];
for (var i = 1; i < arguments.length; i++) {
args[i - 1] = arguments[i];
}
var currentBatch = func.apply(this, args);
var nextBatch = [];
while (currentBatch && currentBatch.length > 0) {
currentBatch.forEach(function(eachFunc) {
var ret = eachFunc();
if (ret && ret.length > 0) {
nextBatch = nextBatch.concat(ret);
}
});
currentBatch = nextBatch;
nextBatch = [];
}
};
/*
* Deep clone an object using the trampoline technique.
*
* @param target {Object} Object to clone
* @return {Object} Cloned object.
*/
function clone(target) {
if (typeof target !== 'object') {
return target;
}
if (target == null || Object.keys(target).length == 0) {
return target;
}
function _clone(b, a) {
var nextBatch = [];
for (var key in b) {
if (typeof b[key] === 'object' && b[key] !== null) {
if (b[key] instanceof Array) {
a[key] = [];
}
else {
a[key] = {};
}
nextBatch.push(_clone.bind(null, b[key], a[key]));
}
else {
a[key] = b[key];
}
}
return nextBatch;
};
var ret = target instanceof Array ? [] : {};
(trampoline.bind(null, _clone))(target, ret);
return ret;
};
克罗克福德建议(我更喜欢)使用此功能:
function object(o) {
function F() {}
F.prototype = o;
return new F();
}
var newObject = object(oldObject);
它是干净的,工作如预期,你不需要图书馆。
编辑:
这是一个对 Object.create 的聚合物,所以你也可以使用它。
var newObject = Object.create(oldObject);
注意: 如果你使用其中的一些,你可能有问题与某些 iteration谁使用 hasOwnProperty. 因为,创建创造新的空的对象,继承旧的对象. 但它仍然有用和实用的克隆对象。
例如,如果 oldObject.a = 5;
newObject.a; // is 5
但:
oldObject.hasOwnProperty(a); // is true
newObject.hasOwnProperty(a); // is false
function clone(obj)
{ var clone = {};
clone.prototype = obj.prototype;
for (property in obj) clone[property] = obj[property];
return clone;
}
使用 Object.create() 获取原型和支持的例子,并使用 for() 圈获取可列的密钥:
function cloneObject(source) {
var key,value;
var clone = Object.create(source);
for (key in source) {
if (source.hasOwnProperty(key) === true) {
value = source[key];
if (value!==null && typeof value==="object") {
clone[key] = cloneObject(value);
} else {
clone[key] = value;
}
}
}
return clone;
}