80 lines
2.4 KiB
JavaScript
80 lines
2.4 KiB
JavaScript
// For nested objects, spread operator only creates new references to the top level fields,
|
|
// the remaining nested fields actually reference the original object which can introduce problems.
|
|
|
|
// The purpose of this method is to deep clone the data in an object recursively, this is useful
|
|
// for cloning modelValues to internal models when regular two-way binding is not an option.
|
|
// See: mobile-location-modal-questions.vue
|
|
|
|
// Creates a deep clone of an object. Clones primitives, arrays and objects, excluding class instances.
|
|
// https://www.30secondsofcode.org/js/s/deep-clone
|
|
export function deepClone(object) {
|
|
if (object === null) {
|
|
return null;
|
|
}
|
|
|
|
const clone = { ...object };
|
|
// eslint-disable-next-line no-return-assign
|
|
Object.keys(clone).forEach((key) =>
|
|
(clone[key] = typeof object[key] === 'object' ? deepClone(object[key]) : object[key]));
|
|
|
|
if (Array.isArray(object)) {
|
|
clone.length = object.length;
|
|
return Array.from(clone);
|
|
}
|
|
|
|
return clone;
|
|
}
|
|
|
|
// The purpose of this method is to check for array or object equality recursively to determine if two complex objects are equal.
|
|
// This is only a comparison of data, not functions.
|
|
export function deepEqual(obj1, obj2) {
|
|
if (typeof obj1 !== typeof obj2) {
|
|
return false;
|
|
}
|
|
|
|
if (obj1 === null || obj2 === null) {
|
|
return obj1 === obj2;
|
|
}
|
|
|
|
if (Array.isArray(obj1) && Array.isArray(obj2)) {
|
|
if (obj1.length !== obj2.length) {
|
|
return false;
|
|
}
|
|
|
|
const sorted1 = obj1.slice().sort();
|
|
const sorted2 = obj2.slice().sort();
|
|
|
|
for (let i = 0; i < sorted1.length; i++) {
|
|
if (!deepEqual(sorted1[i], sorted2[i])) {
|
|
return false;
|
|
}
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
if (typeof obj1 === 'object' && typeof obj2 === 'object') {
|
|
const keys1 = Object.keys(obj1);
|
|
const keys2 = Object.keys(obj2);
|
|
|
|
if (keys1.length !== keys2.length) {
|
|
return false;
|
|
}
|
|
|
|
const sortedKeys1 = keys1.sort();
|
|
const sortedKeys2 = keys2.sort();
|
|
|
|
for (let i = 0; i < sortedKeys1.length; i++) {
|
|
const key1 = sortedKeys1[i];
|
|
const key2 = sortedKeys2[i];
|
|
|
|
if (key1 !== key2 || !deepEqual(obj1[key1], obj2[key2])) {
|
|
return false;
|
|
}
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
return obj1 === obj2;
|
|
}
|