Поверхневе копіювання
Поверхнева копія об'єкта – це копія, чиї властивості поділяють ті самі посилання (вказують на ті самі значення), що й властивості вихідного об'єкта, котрий було скопійовано. Як наслідок, при зміні як вихідного об'єкта, так і копії, може статися видозміна обох об'єктів. Ця логіка відрізняється від логіки глибокого копіювання, при якому вихідний об'єкт і копія є цілковито незалежними.
Більш формально висловлюючись, два об'єкти o1
і o2
є поверхневими копіями одне одного, якщо:
- Вони не одним і тим же об'єктом (
o1 !== o2
). - Властивості
o1
іo2
мають однакові імена в однаковому порядку. - Значення їхніх властивостей – рівні.
- Їхні ланцюжки прототипів – рівні.
Дивіться також визначення структурної рівносильності.
Копія об'єкта, в котрого всі властивості мають примітивні значення, відповідає і визначенню глибокої копії, і визначенню поверхневої. Проте дещо безглуздо говорити про глибину такої копії, адже вона не має вкладених властивостей, а про глибоке копіювання зазвичай говорять в контексті внесення змін до таких вкладених властивостей.
При поверхневому копіюванні копіюються лише властивості найвищого рівня, але не значення вкладених об'єктів. Таким чином:
- Повторне присвоєння властивостей копії найвищого рівня не впливає на вихідний об'єкт.
- Повторне присвоєння властивостей вкладених у копію об'єктів впливає на вихідний об'єкт.
У JavaScript усі стандартні вбудовані операції копіювання об'єктів (синтаксис розгортання, Array.prototype.concat()
, Array.prototype.slice()
, Array.from()
і Object.assign()
) утворюють поверхневі копії, а не глибокі.
Для прикладу – наступний приклад, у якому створюється об'єкт-масив ingredientsList
, а потім шляхом копіювання цього об'єкта ingredientsList
створюється об'єкт ingredientsListCopy
.
const ingredientsList = ["локшина", { list: ["яйця", "борошно", "вода"] }];
const ingredientsListCopy = Array.from(ingredientsList);
console.log(ingredientsListCopy);
// ["локшина",{"list":["яйця","борошно","вода"]}]
Повторне присвоєння значення вкладеної властивості буде помітно на обох об'єктах.
ingredientsListCopy[1].list = ["рисове борошно", "вода"];
console.log(ingredientsList[1].list);
// Array [ "рисове борошно", "вода" ]
Повторне присвоєння значення властивості найвищого рівня (у цьому випадку – індексові 0
) буде помітно лише на зміненому об'єкті.
ingredientsListCopy[0] = "рисова локшина";
console.log(ingredientsList[0]);
console.log(JSON.stringify(ingredientsListCopy));
// ["рисова локшина",{"list":["рисове борошно","вода"]}]
console.log(JSON.stringify(ingredientsList));
// ["локшина",{"list":["рисове борошно","вода"]}]
Дивіться також
- Споріднені терміни глосарія: