我有一个对象x。我想将其复制为对象y,这样对y的更改不会修改x。我意识到复制从内置JavaScript对象派生的对象会导致额外的、不需要的财产。这不是问题,因为我正在复制我自己的一个文字构造对象。
如何正确克隆JavaScript对象?
我有一个对象x。我想将其复制为对象y,这样对y的更改不会修改x。我意识到复制从内置JavaScript对象派生的对象会导致额外的、不需要的财产。这不是问题,因为我正在复制我自己的一个文字构造对象。
如何正确克隆JavaScript对象?
当前回答
这里许多同行针对深度克隆提出的解决方案JSON.parse(JSON.stringify(orig_obj)有几个问题,我发现这些问题如下:
它在复制原始对象中未定义值的条目时丢弃这些条目,如果有一些值,如Infinity、NaN等,它们将在复制时转换为null,如果原始对象中存在Date类型,则它将在克隆对象中字符串化(typeof Date_entry-->string)。
找到了一种克隆对象的有效方法,它在各种场景中都很适合我。请看一看下面的代码,因为它已经解决了JSON.parse(…)的所有上述缺陷,但最终实现了正确的深度克隆:
var orig_obj = {
string: 'my_str',
number: 123,
bool: false,
nul: null,
nested : {
value : true
},
nan : NaN,
date: new Date(),
undef: undefined,
inf: Infinity,
}
console.log("original_obj before modification: ", orig_obj, "\n");
console.log(typeof orig_obj.date, "\n");
var clone_obj = Object.assign({}, orig_obj);
//this below loop will help in deep cloning and solving above issues
for(let prop in orig_obj) {
if(typeof orig_obj[prop] === "object") {
if(orig_obj[prop] instanceof Date)
clone_obj[prop] = orig_obj[prop];
else {
clone_obj[prop] = JSON.parse(JSON.stringify(orig_obj[prop]));
}
}
}
console.log("cloned_obj before modification: ", orig_obj, "\n");
clone_obj.bool = true;
clone_obj.nested.value = "false";
console.log("original_obj post modification: ", orig_obj, "\n");
console.log("cloned_obj post modification: ", clone_obj, "\n");
console.log(typeof clone_obj.date);
其他回答
根据MDN:
如果要浅层复制,请使用Object.assign({},a)对于“深度”复制,请使用JSON.parse(JSON.stringify(a))
不需要外部库,但您需要首先检查浏览器兼容性。
对克隆简单对象感兴趣:
JSON.parse(JSON.stringify(JSON_inoriginal));
来源:如何通过引用将JavaScript对象复制到新变量NOT?
使用Lodash:
var y = _.clone(x, true);
使用npm的深度复制。在浏览器和节点中作为npm模块工作。。。
https://www.npmjs.com/package/deepcopy
设a=深度复制(b)
//
// creates 'clone' method on context object
//
// var
// clon = Object.clone( anyValue );
//
!((function (propertyName, definition) {
this[propertyName] = definition();
}).call(
Object,
"clone",
function () {
function isfn(fn) {
return typeof fn === "function";
}
function isobj(o) {
return o === Object(o);
}
function isarray(o) {
return Object.prototype.toString.call(o) === "[object Array]";
}
function fnclon(fn) {
return function () {
fn.apply(this, arguments);
};
}
function owns(obj, p) {
return obj.hasOwnProperty(p);
}
function isemptyobj(obj) {
for (var p in obj) {
return false;
}
return true;
}
function isObject(o) {
return Object.prototype.toString.call(o) === "[object Object]";
}
return function (input) {
if (isfn(input)) {
return fnclon(input);
} else if (isobj(input)) {
var cloned = {};
for (var p in input) {
owns(Object.prototype, p)
|| (
isfn(input[p])
&& ( cloned[p] = function () { return input[p].apply(input, arguments); } )
|| ( cloned[p] = input[p] )
);
}
if (isarray(input)) {
cloned.length = input.length;
"concat every filter forEach indexOf join lastIndexOf map pop push reduce reduceRight reverse shift slice some sort splice toLocaleString toString unshift"
.split(" ")
.forEach(
function (methodName) {
isfn( Array.prototype[methodName] )
&& (
cloned[methodName] =
function () {
return Array.prototype[methodName].apply(cloned, arguments);
}
);
}
);
}
return isemptyobj(cloned)
? (
isObject(input)
? cloned
: input
)
: cloned;
} else {
return input;
}
};
}
));
//