什么是最有效的方式来克隆一个JavaScript对象?我已经看到obj = eval(uneval(o));被使用,但它是非标准的,仅支持Firefox.我做了事情,如obj = JSON.parse(JSON.stringify(o));但质疑效率。
当前回答
单线 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
其他回答
对于未来的参考,可以使用此代码
第6章:
_clone: function(obj){
let newObj = {};
for(let i in obj){
if(typeof(obj[i]) === 'object' && Object.keys(obj[i]).length){
newObj[i] = clone(obj[i]);
} else{
newObj[i] = obj[i];
}
}
return Object.assign({},newObj);
}
第5章:
function clone(obj){
let newObj = {};
for(let i in obj){
if(typeof(obj[i]) === 'object' && Object.keys(obj[i]).length){
newObj[i] = clone(obj[i]);
} else{
newObj[i] = obj[i];
}
}
return Object.assign({},newObj);
) )
E.G
var obj ={a:{b:1,c:3},d:4,e:{f:6}}
var xc = clone(obj);
console.log(obj); //{a:{b:1,c:3},d:4,e:{f:6}}
console.log(xc); //{a:{b:1,c:3},d:4,e:{f:6}}
xc.a.b = 90;
console.log(obj); //{a:{b:1,c:3},d:4,e:{f:6}}
console.log(xc); //{a:{b:90,c:3},d:4,e:{f:6}}
如下图所示,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)
这里是一个全面的克隆()方法,可以克隆任何JavaScript对象,它处理几乎所有情况:
function clone(src, deep) {
var toString = Object.prototype.toString;
if (!src && typeof src != "object") {
// Any non-object (Boolean, String, Number), null, undefined, NaN
return src;
}
// Honor native/custom clone methods
if (src.clone && toString.call(src.clone) == "[object Function]") {
return src.clone(deep);
}
// DOM elements
if (src.nodeType && toString.call(src.cloneNode) == "[object Function]") {
return src.cloneNode(deep);
}
// Date
if (toString.call(src) == "[object Date]") {
return new Date(src.getTime());
}
// RegExp
if (toString.call(src) == "[object RegExp]") {
return new RegExp(src);
}
// Function
if (toString.call(src) == "[object Function]") {
//Wrap in another method to make sure == is not true;
//Note: Huge performance issue due to closures, comment this :)
return (function(){
src.apply(this, arguments);
});
}
var ret, index;
//Array
if (toString.call(src) == "[object Array]") {
//[].slice(0) would soft clone
ret = src.slice();
if (deep) {
index = ret.length;
while (index--) {
ret[index] = clone(ret[index], true);
}
}
}
//Object
else {
ret = src.constructor ? new src.constructor() : {};
for (var prop in src) {
ret[prop] = deep
? clone(src[prop], true)
: src[prop];
}
}
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
有很多答案,但没有一个给了我需要的效果,我想利用jQuery的深复制的力量......但是,当它进入一个序列时,它只是复制了对序列的参考,并深复制了其中内容。
(它甚至检查 kendo.data.ObservableArray 如果你想要它! 但是, 确保你打电话 kendo.observable(newItem) 如果你想 Arrays 再次可观察。
所以,要完全复制一个现有项目,你只是这样做:
var newItem = jQuery.extend(true, {}, oldItem);
createNewArrays(newItem);
function createNewArrays(obj) {
for (var prop in obj) {
if ((kendo != null && obj[prop] instanceof kendo.data.ObservableArray) || obj[prop] instanceof Array) {
var copy = [];
$.each(obj[prop], function (i, item) {
var newChild = $.extend(true, {}, item);
createNewArrays(newChild);
copy.push(newChild);
});
obj[prop] = copy;
}
}
}