Документация $.extend
гласит следующее:
Не определенные свойства не копируются.Однако свойства, унаследованные от прототипа объекта , будут скопированы . Свойства, которые представляют собой объекты, созданные с помощью new MyCustomObject(args)
, или встроенные типы JavaScript, такие как Date или RegExp, не восстанавливаются и будут отображаться как простые объекты в результирующем объекте или массиве.
Это означает, что массив со всеми простыми объектами в нем будет глубоко объединен / скопирован.Однако объекты, созданные с ключевым словом new
, восстановлены не будут.Это оставляет нам следующий сценарий:
Копирование массива работает очень хорошо, однако, поскольку элементы в массиве создаются с использованием ключевого слова new
, они больше не объединяются.При изменении самого массива (push, popping и т. Д.) Вы можете видеть, что массив действительно является копией.
Проблема здесь в том, что вы обращаетесь к одному из элементов в массиве и изменяете объект (созданныйс ключевым словом new
).Оба массива по-прежнему указывают на один и тот же объект, поэтому при чтении из другого массива, который содержит ту же ссылку на объект, вы также увидите это изменение.
Чтобы решить эту проблему, вы также должны сделать копию каждого объекта в массиве.В зависимости от вашего варианта использования вы можете использовать Object.assign
или Object.create
, прежде чем использовать их вслепую, ознакомьтесь с документацией.
I 'Мы также создали минимальный пример проблемы, с которой вы сталкиваетесь, чтобы дать вам лучшее понимание проблемы.
// setup
var array1, array2, array3, array4;
function Dummy(name) { this.name = name }
// test #1 - using plain objects
array1 = [{ name: 'Foo' }];
array2 = $.extend(true, [], array1);
array1[0].name = 'Bar';
console.log(array1[0].name, array2[0].name);
// test #2 - using the `new` keyword
array3 = [new Dummy('Foo')];
array4 = $.extend(true, [], array3);
array3[0].name = 'Bar';
console.log(array3[0].name, array4[0].name);
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/1.12.4/jquery.min.js"></script>