在 javascript 中深度复制嵌套对象数组
Deep copying array of nested objects in javascript
我正在尝试深度复制 javascript 中的嵌套对象数组。我的阵列看起来像这样
var arr = [{name:"adam",age:"21"},
{name:"freddie",age:"35",children:[{name:"mercury",age:"25"}]},
{name:"jim",age:"35",children:[{name:"morrison",age:"25",children:[{name:"some", age:"40"}]}]}
];
我想对数组中的每个对象进行深度复制,我想将 arr 的精确副本创建到不应有对象引用的新数组中。数组的深度也是未知的,即子数组可以达到任何级别。
我经历过这个 link
Copying of an array of objects to another Array without object reference in javascript(Deep copy) 但这对我没有帮助。我用谷歌搜索并在 jQuery 中找到了一些解决方案,但这对我没有帮助,因为我不了解 jQuery。
我也尝试过用递归来实现它,但是那也行不通
http://ideone.com/kJi5X3
我只想在 javascript 中完成,而不使用 jQuery 或任何东西。我是 JavaScript 的新手,所以如果有任何库或简单的方法可以做到这一点,我可能会错过。
请帮我解决这个问题。提前致谢。
您有两个主要选择:
使用JSON.stringify
和JSON.parse
:
var copy = JSON.parse(JSON.stringify(original));
但是我从来不喜欢那样。通过文本的往返充其量是低效的,它不会正确处理函数或 Date
、RegExp
、undefined
等值,除非您编写替换器和恢复器。
- 使用递归函数,像这样:
var toString = Object.prototype.toString;
function deepCopy(obj) {
var rv;
switch (typeof obj) {
case "object":
if (obj === null) {
// null => null
rv = null;
} else {
switch (toString.call(obj)) {
case "[object Array]":
// It's an array, create a new array with
// deep copies of the entries
rv = obj.map(deepCopy);
break;
case "[object Date]":
// Clone the date
rv = new Date(obj);
break;
case "[object RegExp]":
// Clone the RegExp
rv = new RegExp(obj);
break;
// ...probably a few others
default:
// Some other kind of object, deep-copy its
// properties into a new object
rv = Object.keys(obj).reduce(function(prev, key) {
prev[key] = deepCopy(obj[key]);
return prev;
}, {});
break;
}
}
break;
default:
// It's a primitive, copy via assignment
rv = obj;
break;
}
return rv;
}
var a = [1, {foo: "bar"}, ['a', 'b'], new Date()];
snippet.log(JSON.stringify(a));
var b = deepCopy(a);
snippet.log(JSON.stringify(b));
<!-- Script provides the `snippet` object, see http://meta.stackexchange.com/a/242144/134069 -->
<script src="http://tjcrowder.github.io/simple-snippets-console/snippet.js"></script>
请注意,上面使用的是所有现代浏览器都存在的 ES5 功能,但不是一些较旧的浏览器,如 IE8。但是,对于旧版浏览器,上面使用的所有功能都可以填充。
这不会尝试处理自定义构造函数或保留数组中对象的原型;这样做会使事情 戏剧性地 变得更加复杂,并且如果没有关于如何调用这些构造函数进行复制操作的约定,就不可能完美。您可以通过分配相同的原型来关闭,但这不会解释构造函数中的逻辑,特别是对于在其中设置为闭包的函数。
我正在尝试深度复制 javascript 中的嵌套对象数组。我的阵列看起来像这样
var arr = [{name:"adam",age:"21"},
{name:"freddie",age:"35",children:[{name:"mercury",age:"25"}]},
{name:"jim",age:"35",children:[{name:"morrison",age:"25",children:[{name:"some", age:"40"}]}]}
];
我想对数组中的每个对象进行深度复制,我想将 arr 的精确副本创建到不应有对象引用的新数组中。数组的深度也是未知的,即子数组可以达到任何级别。 我经历过这个 link Copying of an array of objects to another Array without object reference in javascript(Deep copy) 但这对我没有帮助。我用谷歌搜索并在 jQuery 中找到了一些解决方案,但这对我没有帮助,因为我不了解 jQuery。
我也尝试过用递归来实现它,但是那也行不通 http://ideone.com/kJi5X3
我只想在 javascript 中完成,而不使用 jQuery 或任何东西。我是 JavaScript 的新手,所以如果有任何库或简单的方法可以做到这一点,我可能会错过。 请帮我解决这个问题。提前致谢。
您有两个主要选择:
使用
JSON.stringify
和JSON.parse
:var copy = JSON.parse(JSON.stringify(original));
但是我从来不喜欢那样。通过文本的往返充其量是低效的,它不会正确处理函数或 Date
、RegExp
、undefined
等值,除非您编写替换器和恢复器。
- 使用递归函数,像这样:
var toString = Object.prototype.toString;
function deepCopy(obj) {
var rv;
switch (typeof obj) {
case "object":
if (obj === null) {
// null => null
rv = null;
} else {
switch (toString.call(obj)) {
case "[object Array]":
// It's an array, create a new array with
// deep copies of the entries
rv = obj.map(deepCopy);
break;
case "[object Date]":
// Clone the date
rv = new Date(obj);
break;
case "[object RegExp]":
// Clone the RegExp
rv = new RegExp(obj);
break;
// ...probably a few others
default:
// Some other kind of object, deep-copy its
// properties into a new object
rv = Object.keys(obj).reduce(function(prev, key) {
prev[key] = deepCopy(obj[key]);
return prev;
}, {});
break;
}
}
break;
default:
// It's a primitive, copy via assignment
rv = obj;
break;
}
return rv;
}
var a = [1, {foo: "bar"}, ['a', 'b'], new Date()];
snippet.log(JSON.stringify(a));
var b = deepCopy(a);
snippet.log(JSON.stringify(b));
<!-- Script provides the `snippet` object, see http://meta.stackexchange.com/a/242144/134069 -->
<script src="http://tjcrowder.github.io/simple-snippets-console/snippet.js"></script>
请注意,上面使用的是所有现代浏览器都存在的 ES5 功能,但不是一些较旧的浏览器,如 IE8。但是,对于旧版浏览器,上面使用的所有功能都可以填充。
这不会尝试处理自定义构造函数或保留数组中对象的原型;这样做会使事情 戏剧性地 变得更加复杂,并且如果没有关于如何调用这些构造函数进行复制操作的约定,就不可能完美。您可以通过分配相同的原型来关闭,但这不会解释构造函数中的逻辑,特别是对于在其中设置为闭包的函数。