什么是最有效的方式来克隆一个JavaScript对象?我已经看到obj = eval(uneval(o));被使用,但它是非标准的,仅支持Firefox.我做了事情,如obj = JSON.parse(JSON.stringify(o));但质疑效率。
当前回答
这是一个回归的解决方案:
obj = { a: { b: { c: { d: ['1', '2'] } } }, e: 'Saeid' } const Clone = function (obj) { const container = Array.isArray(obj) ? [] : {} const keys = Object.keys(obj) for (let i = 0; i < keys.length; i++) { const key = keys[i] if(typeof obj[key] == 'object') { container[key] = Clone(obj[key]) } else container[key] = obj[key].slice() } return container } console.log(Clone(obj))
其他回答
如下图所示,John Resig的jQuery克隆器将非数字属性的<unk>转化为非数字属性的对象,而RegDwight的JSON克隆器将非数字属性放下。
function jQueryClone(obj) {
return jQuery.extend(true, {}, obj)
}
function JSONClone(obj) {
return JSON.parse(JSON.stringify(obj))
}
var arrayLikeObj = [[1, "a", "b"], [2, "b", "a"]];
arrayLikeObj.names = ["m", "n", "o"];
var JSONCopy = JSONClone(arrayLikeObj);
var jQueryCopy = jQueryClone(arrayLikeObj);
alert("Is arrayLikeObj an array instance?" + (arrayLikeObj instanceof Array) +
"\nIs the jQueryClone an array instance? " + (jQueryCopy instanceof Array) +
"\nWhat are the arrayLikeObj names? " + arrayLikeObj.names +
"\nAnd what are the JSONClone names? " + JSONCopy.names)
扩展操作器... (原始序列 - 仅) 序列(0) (原始序列 - 仅) 序列() (原始序列 - 仅) concat() (原始序列 - 仅) 定制功能,如下所示(每个序列) jQuery 的 $.extend() (每个序列) JSON.parse(JSON.stringify()) (原始和字面序列 - 仅) Underscore 的 _.clone() (原始和字面序列 - 仅) Lodash 的 _.cloneDeep() (每个序列)
let arr1a = [1, 'a', true];
let arr1b = [...arr1a];
而且在哪裡 slice() 比 concat( 有更好的性能: https://jsbench.me/x5ktn7o94d/
let arr1c = arr1a.splice(0);
let arr1d = arr1a.slice();
let arr1e = arr1a.concat();
let arr2a = [1, 'a', true, {}, []];
let arr2b = JSON.parse(JSON.stringify(arr2a));
let arr3a = [1, 'a', true, {}, [], new Object()];
function copy(aObject) {
// Prevent undefined objects
// if (!aObject) return aObject;
let bObject = Array.isArray(aObject) ? [] : {};
let value;
for (const key in aObject) {
// Prevent self-references to parent object
// if (Object.is(aObject[key], aObject)) continue;
value = aObject[key];
bObject[key] = (typeof value === "object") ? copy(value) : value;
}
return bObject;
}
let arr3b = copy(arr3a);
或使用第三方实用功能:
let arr3c = $.extend(true, [], arr3a); // jQuery Extend
let arr3d = _.cloneDeep(arr3a); // Lodash
注意: jQuery 的 $.extend 也比 JSON.parse(JSON.stringify() 表现更好):
克罗克福德建议(我更喜欢)使用此功能:
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
在我的经验中,一个重复版本大大超越了JSON.parse(JSON.stringify(obj))。这里是一个现代化的重复深对象复制功能,可以在单一线上匹配:
function deepCopy(obj) {
return Object.keys(obj).reduce((v, d) => Object.assign(v, {
[d]: (obj[d].constructor === Object) ? deepCopy(obj[d]) : obj[d]
}), {});
}
这比JSON.parse方法快40倍。
单线 ECMAScript 6 解决方案(特殊对象类型如 Date/Regex 未处理):
const clone = (o) => typeof o === 'object' && o!== null? // only clone objects (Array.isArray(o)? // if cloning an array o.map(e => clone(e)) : // clone each of its elements Object.keys(o).reduce( // otherwise reduce every key in the object (r, k) => (r[k] = clone(o[k]), r), {} // and save its cloned value