Резюме: в этом уроке вы узнаете, как копировать объекты в JavaScript, включая поверхностное и глубокое копирование. Чтобы скопировать объект в JavaScript, у вас есть три варианта:
- Использовать синтаксис распространения (
...
). - Использовать метод
Object.assign()
- Использовать методы
JSON.stringify()
иJSON.parse()
.
Ниже показано, как скопировать объект, используя три вышеуказанных метода:
Code language: JavaScript (javascript)const person = { firstName: 'John', lastName: 'Doe' }; // using spread ... let p1 = { ...person }; // using Object.assign() method let p2 = Object.assign({}, person); // using JSON let p3 = JSON.parse(JSON.stringify(person));
И spread (...
) и Object.assign()
выполняют неглубокое копирование, в то время как методы JSON выполняют глубокое копирование.
Неглубокое копирование против глубокого копирования
В JavaScript вы используете переменные для хранения значений, которые могут быть примитивами или ссылками. Когда вы делаете копию значения, хранящегося в переменной, вы создаете новую переменную с тем же значением. Для примитивного значения вы просто используете простое присваивание:
Code language: JavaScript (javascript)let counter = 1; let copiedCounter = counter;
И когда вы изменяете значение скопированной переменной, значение оригинала остается прежним.
Code language: JavaScript (javascript)copiedCounter = 2; console.log(counter);
Вывод:
1
Однако если вы используете оператор присваивания для ссылочного значения, он не будет копировать значение. Вместо этого обе переменные будут ссылаться на один и тот же объект в памяти:
Code language: JavaScript (javascript)let person = { firstName: 'John', lastName: 'Doe' }; let copiedPerson = person;
И когда вы обращаетесь к объекту через новую переменную (copiedPerson) и изменяете значение ее свойства (name), вы изменяете значение свойства объекта.
Code language: JavaScript (javascript)copiedPerson.firstName = 'Jane'; console.log(person);
Вывод:
Code language: CSS (css){ firstName: 'Jane', lastName: 'Doe' }
Глубокое копирование означает, что значение новой переменной отвязано от исходной переменной, а неглубокое копирование означает, что некоторые значения все еще связаны с исходной переменной.
Пример неглубокого копирования
Рассмотрим следующий пример:
Code language: JavaScript (javascript)let person = { firstName: 'John', lastName: 'Doe', address: { street: 'North 1st street', city: 'San Jose', state: 'CA', country: 'USA' } }; let copiedPerson = Object.assign({}, person); copiedPerson.firstName = 'Jane'; // disconnected copiedPerson.address.street = 'Amphitheatre Parkway'; // connected copiedPerson.address.city = 'Mountain View'; // connected console.log(copiedPerson);
В этом примере:
- Во-первых, создайте новый объект с именем
person
. - Во-вторых, клонируйте объект
person
с помощью методаObject.assign()
. - В-третьих, измените имя и адрес объекта
copiedPerson
.
Вот вывод:
Code language: CSS (css){ firstName: 'Jane', lastName: 'Doe', address: { street: 'Amphitheatre Parkway', city: 'Mountain View', state: 'CA', country: 'USA' } }
Однако, когда вы покажете значения объекта person, вы обнаружите, что изменилась информация об адресе, но изменилось имя:
Code language: JavaScript (javascript)console.log(person);
Output:
Code language: CSS (css){ firstName: 'John', lastName: 'Doe', address: { street: 'Amphitheatre Parkway', city: 'Mountain View', state: 'CA', country: 'USA' } }
Причина в том, что адрес является справочным значением, а имя — примитивным значением. И person
, и copiedPerson
ссылаются на разные объекты, но эти объекты ссылаются на один и тот же объект address
.
Пример глубокого копирования
Следующий фрагмент заменяет метод Object.assign()
на методы JSON для глубокого копирования объекта person
:
Code language: JavaScript (javascript)let person = { firstName: 'John', lastName: 'Doe', address: { street: 'North 1st street', city: 'San Jose', state: 'CA', country: 'USA' } }; let copiedPerson = JSON.parse(JSON.stringify(person)); copiedPerson.firstName = 'Jane'; // disconnected copiedPerson.address.street = 'Amphitheatre Parkway'; copiedPerson.address.city = 'Mountain View'; console.log(person);
Выход
Code language: CSS (css){ firstName: 'John', lastName: 'Doe', address: { street: 'North 1st street', city: 'San Jose', state: 'CA', country: 'USA' } }
В этом примере все значения в объекте copiedPerson
отделены от исходного объекта person
. В этом уроке вы узнали, как копировать объекты в JavaScript с помощью поверхностного или глубокого копирования.