Глубокое копирование массива вложенных объектов в 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 в новый массив, который не должен иметь ссылку на объект. Глубина массива также неизвестна, что дочерний массив может быть до любого уровня. Я прошел через эту ссылку Копирование массива объектов в другой массив без ссылки на объект в javascript (Deep copy), но это меня не помогло. Я googled и нашел некоторые решения в jQuery, но это не помогло мне, так как я не знаю jQuery.

Я также попытался реализовать его с рекурсией, но это тоже не работает http://ideone.com/kJi5X3

Я хочу сделать это только в javascript, не используя jQuery или что-нибудь еще. Я новичок в JavaScript, поэтому я, возможно, пропустил, если есть библиотека или простой способ сделать это. Пожалуйста, помогите мне решить эту проблему. Спасибо заранее.

Ответ 1

У вас есть два основных варианта:

  • Используйте 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 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 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>