javascript javascript中嵌套对象的深度复制数组

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/28876300/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-28 09:42:07  来源:igfitidea点击:

Deep copying array of nested objects in javascript

javascriptarraysdeep-copy

提问by user2912611

I am trying to deep copy array of nested objects in javascript. My array look like this

我正在尝试在 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"}]}]}
    ];

I want to make a deep copy of every object inside the array that is i want to create a exact copy of arr into new array which should not have object reference. Depth of array is also unknown that is children array can be upto any level. I have gone through this link Copying of an array of objects to another Array without object reference in javascript(Deep copy)but that did not help me. I googled and found some solutions in jQuery but that did not help me as i dont have knowledge of jQuery.

我想对数组中的每个对象进行深层复制,即我想将 arr 的精确副本创建到不应具有对象引用的新数组中。数组的深度也是未知的,即子数组可以达到任何级别。我已经通过这个链接 将对象数组复制到另一个数组而没有 javascript(深度复制)中的对象引用,但这对我没有帮助。我在 jQuery 中搜索并找到了一些解决方案,但这对我没有帮助,因为我不了解 jQuery。

I also tried implementing it with recursion but that's not working too http://ideone.com/kJi5X3

我也尝试用递归来实现它,但这也不起作用 http://ideone.com/kJi5X3

I want to do it in javascript only without using jQuery or anything. I am new to JavaScript so i may have missed if there is any library or simple method to do this. Please help me to solve this problem. Thanks in advance.

我只想在不使用 jQuery 或任何东西的情况下在 javascript 中做到这一点。我是 JavaScript 的新手,所以如果有任何库或简单的方法可以做到这一点,我可能会错过。请帮我解决这个问题。提前致谢。

回答by T.J. Crowder

You have two main options:

您有两个主要选择:

  1. Use JSON.stringifyand JSON.parse:

    var copy = JSON.parse(JSON.stringify(original));
    

    ButI've never liked that. A round-trip through text is inefficient at best, and it won't handle Date, RegExp, undefined, etc. values correctly unless you write a replacer and a reviver.

  2. Use a recursive function, something like this:

  1. 使用JSON.stringifyJSON.parse

    var copy = JSON.parse(JSON.stringify(original));
    

    我从来不喜欢那样。文本往返充其量是低效的,除非您编写替换程序和恢复程序,否则它无法正确处理DateRegExpundefined等值。

  2. 使用递归函数,如下所示:

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>

Note that the above uses ES5 features present on all modern browsers but not some older ones, like IE8. All of the features used above can be polyfilled, however, for older browsers.

请注意,以上使用了所有现代浏览器上都存在的 ES5 功能,但不包括一些较旧的浏览器,例如 IE8。但是,对于较旧的浏览器,上面使用的所有功能都可以使用 polyfill。

That doesn't try to get into handling custom constructor functions or preserving prototypes on objects in the array; doing so makes things dramaticallymore complicated and impossible to make perfect without a convention for how to call those constructors for a copy operation. You can get close by assigning the same prototype, but that wouldn't account for logic within the constructor function and in particular for functions set up as closures within it.

这并不试图处理自定义构造函数或保留数组中对象的原型;这样做使事情变得显着,而不对如何调用这些构造函数的复制操作的公约更加复杂,不可能做出完美。您可以通过分配相同的原型来接近,但这不会考虑构造函数中的逻辑,特别是对于在其中设置为闭包的函数。