class export class Utils { memberof constructor ( ) { this . toString = Object . prototype . toString ; } param { * } obj returns { * } memberof public deepClone ( target ) { if ( typeof target !== 'object' || target === null ) return target ; const targetClone = Array . isArray ( target ) ? [ ] : { } ; for ( const key in target ) if ( target . hasOwnProperty ( key ) ) targetClone [ key ] = this . deepClone ( target [ key ] ) ; return targetClone ; } param { * } object returns { string } memberof public buildQuery ( object ) { if ( ! object || ! ( object instanceof Object ) ) return '' ; let query = '?' ; for ( const key in object ) { if ( ! ( object [ key ] instanceof Object ) ) { query += `${ key }=${ object [ key ] . toString ( ) }&` ; } else { query += `${ key }=${ JSON . stringify ( object [ key ] ) }&` ; } } return query . slice ( 0 , query . length - 1 ) ; } param { * } func returns { boolean } memberof public isFunction ( func ) { return this . toString . call ( func ) === '[object Function]' ; } param { * } a param { * } b param { any [ ] } aStack param { any [ ] } bStack returns { boolean } memberof public isEqual ( a , b , aStack ? , bStack ? ) { if ( a === b ) return a !== 0 || 1 / a === 1 / b ; if ( a == null || b == null ) return false ; if ( a !== a ) return b !== b ; const type = typeof a ; if ( type !== 'function' && type !== 'object' && typeof b !== 'object' ) return false ; return this . deepIsEqual ( a , b , aStack , bStack ) ; } param { * } a param { * } b param { any [ ] } aStack param { any [ ] } bStack returns { boolean } memberof public deepIsEqual ( a , b , aStack ? , bStack ? ) { const className = this . toString . call ( a ) ; if ( className !== this . toString . call ( b ) ) return false ; switch ( className ) { case '[object RegExp]' : case '[object String]' : return `${ a }` === `${ b }` ; case '[object Number]' : { if ( + a !== + a ) return + b !== + b ; return + a === 0 ? 1 / + a === 1 / b : + a === + b ; } case '[object Date]' : case '[object Boolean]' : return + a === + b ; } const areArrays = className === '[object Array]' ; if ( ! areArrays ) { if ( typeof a !== 'object' || typeof b !== 'object' ) return false ; const aCtor = a . constructor ; const bCtor = b . constructor ; if ( aCtor !== bCtor && ! ( this . isFunction ( aCtor ) && aCtor instanceof aCtor && this . isFunction ( bCtor ) && bCtor instanceof bCtor ) && ( 'constructor' in a && 'constructor' in b ) ) { return false ; } } aStack = aStack || [ ] ; bStack = bStack || [ ] ; let length = aStack . length ; while ( length -- ) { if ( aStack [ length ] === a ) { return bStack [ length ] === b ; } } aStack . push ( a ) ; bStack . push ( b ) ; if ( areArrays ) { length = a . length ; if ( length !== b . length ) return false ; while ( length -- ) { if ( ! this . isEqual ( a [ length ] , b [ length ] , aStack , bStack ) ) return false ; } } else { const keys = Object . keys ( a ) ; let key ; length = keys . length ; if ( Object . keys ( b ) . length !== length ) return false ; while ( length -- ) { key = keys [ length ] ; if ( b && ! ( b . hasOwnProperty ( key ) && this . isEqual ( a [ key ] , b [ key ] , aStack , bStack ) ) ) return false ; } } aStack . pop ( ) ; bStack . pop ( ) ; return true ; } returns { boolean } memberof public hasWindowAndDocument ( ) { return typeof window !== 'undefined' && typeof window . document !== 'undefined' ; } } export const utils = new Utils ( ) ;