param a param b export function equals ( a , b ) { if ( a === b ) { return true ; } const isArrA = Array . isArray ( a ) ; const isArrB = Array . isArray ( b ) ; if ( isArrA && isArrB ) { const al = a . length ; if ( al !== b . length ) { return false ; } for ( let i = 0 ; i < al ; i ++ ) { if ( ! equals ( a [ i ] , b [ i ] ) ) { return false ; } } return true ; } if ( isArrA !== isArrB ) { return false ; } if ( a && b && typeof a === "object" && typeof b === "object" ) { const keys = Object . keys ( a ) ; const keysLength = keys . length ; if ( keysLength !== Object . keys ( b ) . length ) { return false ; } const isDateA = a instanceof Date ; const isDateB = b instanceof Date ; if ( isDateA && isDateB ) { return a . getTime ( ) === b . getTime ( ) ; } if ( isDateA !== isDateB ) { return false ; } const isRegexpA = a instanceof RegExp ; const isRegexpB = b instanceof RegExp ; if ( isRegexpA && isRegexpB ) { return a . toString ( ) === b . toString ( ) ; } if ( isRegexpA !== isRegexpB ) { return false ; } for ( let i = 0 ; i < keysLength ; i ++ ) { if ( ! b . hasOwnProperty ( keys [ i ] ) ) { return false ; } } for ( let i = 0 ; i < keysLength ; i ++ ) { if ( ! equals ( a [ keys [ i ] ] , b [ keys [ i ] ] ) ) { return false ; } } return true ; } return false ; } param a param b export function contains ( a , b ) { const containsInternal = ( x , y , isToplevel ) => { if ( Array . isArray ( x ) ) { if ( ! Array . isArray ( y ) ) { if ( isToplevel && ( y === null || typeof y !== "object" ) ) { return x . some ( xv => xv === y ) ; } return false ; } return y . every ( yv => x . some ( xv => containsInternal ( xv , yv , false ) ) ) ; } if ( x && typeof x === "object" ) { if ( typeof y !== "object" ) { return false ; } return Object . keys ( y ) . every ( yk => x . hasOwnProperty ( yk ) && containsInternal ( x [ yk ] , y [ yk ] , false ) ) ; } return x === y ; } ; return containsInternal ( a , b , true ) ; } param a param b export function includes ( a , b ) { if ( ! Array . isArray ( a ) ) { throw new TypeError ( `first argument must be an array` ) ; } return a . some ( av => equals ( av , b ) ) ; } param obj export function clone ( obj ) { return cloneDeep ( obj , new Set < object > ( ) ) ; } function cloneDeep ( obj , refs ) { if ( obj === undefined || obj === null || typeof obj === "number" || typeof obj === "boolean" || typeof obj === "string" ) { return obj ; } if ( Array . isArray ( obj ) ) { return obj . map ( o => { const value = cloneDeep ( o , refs ) ; return ( value === undefined ) ? null : value ; } ) ; } if ( typeof obj === "object" ) { if ( obj instanceof Number || obj instanceof Boolean || obj instanceof String ) { return obj . valueOf ( ) ; } if ( obj instanceof Date ) { return obj . toJSON ( ) ; } if ( refs . has ( obj ) ) { throw new TypeError ( "Cloning circular structure not supported" ) ; } refs . add ( obj ) ; const cloned = { } ; for ( const prop in obj ) { if ( typeof prop !== "string" ) { continue ; } const value = cloneDeep ( obj [ prop ] , refs ) ; if ( value !== undefined ) { cloned [ prop ] = value ; } } return cloned ; } return undefined ; }