UNPKG

@gravityforms/utils

Version:
110 lines (96 loc) 2.45 kB
/** * @module cloneDeep * @description Performs a deep clone of the specified variable and returns the cloned variable. * * @since 3.1.0 * * @param {*} value The value to clone. * * @return {*} Returns a deep copy of the specified variable. * * @example * import { cloneDeep } from "@gravityforms/utils"; * * function Example() { * const obj = { prop: 'val' }; * const clone = cloneDeep( obj ); * } * */ const cloneDeep = ( value ) => { return _cloneDeepSafe( value ); }; /** * @function _cloneDeepSafe * @description Performs a deep clone of the specified variable and returns the cloned variable. * * @since 3.1.0 * * @param {*} value The value to clone. * @param {WeakMap} seen A WeakMap to handle circular references. * * @return {*} Returns a deep copy of the specified variable. * */ const _cloneDeepSafe = ( value, seen = new WeakMap() ) => { // Handle null, undefined, or primitive types if ( value === null || typeof value !== 'object' ) { return value; } // Handle circular references if ( seen.has( value ) ) { return seen.get( value ); } // Handle Date objects if ( value instanceof Date ) { return new Date( value ); } // Handle Arrays if ( Array.isArray( value ) ) { const copy = []; seen.set( value, copy ); for ( let i = 0; i < value.length; i++ ) { copy[ i ] = _cloneDeepSafe( value[ i ], seen ); } return copy; } // Handle Map if ( value instanceof Map ) { const copy = new Map(); seen.set( value, copy ); value.forEach( ( v, k ) => { copy.set( k, _cloneDeepSafe( v, seen ) ); } ); return copy; } // Handle Set if ( value instanceof Set ) { const copy = new Set(); seen.set( value, copy ); value.forEach( ( v ) => { copy.add( _cloneDeepSafe( v, seen ) ); } ); return copy; } // Handle RegExp if ( value instanceof RegExp ) { return new RegExp( value ); } // Handle Typed Arrays if ( ArrayBuffer.isView( value ) ) { return new value.constructor( value.buffer.slice( 0 ) ); } // Handle plain objects and prototypes if ( value instanceof Object ) { const copy = Object.create( Object.getPrototypeOf( value ) ); seen.set( value, copy ); const keys = Reflect.ownKeys( value ); for ( const key of keys ) { copy[ key ] = _cloneDeepSafe( value[ key ], seen ); } return copy; } // If the value is an unsupported type, return it as is (functions, etc.) return value; }; export default cloneDeep;