#javascript
#typescript #ecmascript-6 #глубокая копия #неглубокая копия
Вопрос:
Согласно приведенному здесь примеру,
let first:number[] = [1, 2];
let second:number[] = [3, 4];
let both_plus:number[] = [0, ...first, ...second, 5];
console.log(`both_plus is ${both_plus}`);
first[0] = 20;
console.log(`first is ${first}`);
console.log(`both_plus is ${both_plus}`);
both_plus[1]=30;
console.log(`first is ${first}`);
console.log(`both_plus is ${both_plus}`);
Распространение показывает глубокую копию, потому что все три массива имеют собственные дубликаты, основанные на приведенных ниже выходных данных:
both_plus is 0,1,2,3,4,5
first is 20,2
both_plus is 0,1,2,3,4,5
first is 20,2
both_plus is 0,30,2,3,4,5
В документации говорится: Распространение создает неглубокую копию first
и second
. Как я это понимаю?
Комментарии:
1. Это то же самое, что
[0, 1, 2, 3, 4, 5]
. Вы не можете точно сказать, является ли копия глубокой, если все, что у вас есть, — это примитивы.2. Нет, синтаксис распространения ничего не создает и не копирует. Это литерал массива, который создает новый массив.
Ответ №1:
В вашем случае неглубокая копия и глубокая копия — это одно и то же. Для массива, содержащего только примитивы, они всегда будут идентичны. Вы заметите разницу, только когда ваш массив будет содержать другие объекты.
Javascript передается по значению, поэтому, когда массив копируется неглубоко (например, с помощью spread), каждое значение из исходного массива копируется в новый массив. В случае примитива значение копируется напрямую, и внесенные в него изменения не влияют на оригинал.
Однако, когда массив содержит объекты, каждое значение само по себе является ссылкой на что-то другое. Таким образом, даже если ссылка была скопирована в новый массив, она по-прежнему указывает на то же самое, что и ссылка в исходном массиве. Таким образом, хотя изменение нового массива не изменит оригинал, изменение элементов массива повлияет на оригинал.
Вот пример:
const objArray = [{foo: "bar"}];
const shallowCopy = [...objArray];
// Changing the array itself does not change the orignal. Note the
// original still only has one item, but the copy has two:
shallowCopy.push({foo: "baz"});
console.log("objArray after push:", objArray);
console.log("shallowCopy after push:", shallowCopy);
// However, since shallowCopy[0] is a reference pointing to the same object
// as objArray[0], mutating either will change the other:
shallowCopy[0].foo = "something else";
console.log("objArray after mutation:", objArray);
console.log("shallowCopy after mutation:", shallowCopy);
Ответ №2:
Неглубокая копия означает, что все элементы из first
и second
просто добавляются в новый массив, новую копию. Глубокое копирование будет означать, что все элементы из first
и second
сначала копируются, а затем добавляются в новый массив.
Различие заключается в том, копируются ли сами элементы в новый объект перед добавлением в новый массив.
Используя примитивы, такие как числа, на самом деле невозможно проиллюстрировать разницу, но если вы используете объекты, разница довольно очевидна.
Допустим, у вас есть что-то вроде этого:
let first = [{foo: 'bar'}];
let second = [{fizz: 'buzz'}];
let both = [...first, ...second];
Поскольку распространение приводит к неглубокой копии, можно ожидать, что соответствующие объекты пройдут тест на равенство:
first[0] === both[0]; // true
second[0] === both[1]; // true
Но если распространение привело к глубокой копии, вы ожидаете, что тест на равенство завершится неудачей:
first[0] === both[0]; // false
second[0] === both[1]; // false
Комментарии:
1. На моей машине результаты, оцененные в
first[0] === both[0]; // false
,second[0] === both[1]; // true
Ответ №3:
Распространение приводит к неглубокой копии
const a = [{x: 1}, {y: 1}];
const b = a;
const c = [...a, ...b];
console.log(c); // [{x: 1}, {y: 1}, {x: 1}, {y: 1}]
a[1]['y'] = 5;
console.log(c); // [{x: 1}, {y: 5}, {x: 1}, {y: 5}]