// 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; } export function getPropertyCaseInsensitive(obj, property) { const props = []; for (const i in obj) if (Object.prototype.hasOwnProperty.call(obj, i)) props.push(i); let prop; // eslint-disable-next-line no-cond-assign while (prop = props.pop()) if (prop.toLowerCase() === property.toLowerCase()) return prop; return null; }