param { Object } val returns { boolean } function isArray ( val ) { return toString . call ( val ) === '[object Array]' ; } param { Object } val return { boolean } function isPlainObject ( val ) { if ( toString . call ( val ) !== '[object Object]' ) { return false ; } const prototype = Object . getPrototypeOf ( val ) ; return prototype === null || prototype === Object . prototype ; } param { Object | Array } obj param { Function } fn function forEach ( obj , fn ) { if ( obj === null || typeof obj === 'undefined' ) { return ; } if ( typeof obj !== 'object' ) { obj = [ obj ] ; } if ( isArray ( obj ) ) { for ( let i = 0 , l = obj . length ; i < l ; i ++ ) { fn . call ( null , obj [ i ] , i , obj ) ; } } else { for ( const key in obj ) { if ( Object . prototype . hasOwnProperty . call ( obj , key ) ) { fn . call ( null , obj [ key ] , key , obj ) ; } } } } param { Object } obj1 returns { Object } function merge ( ... args ) { const result = { } ; function assignValue ( val , key ) { if ( isPlainObject ( result [ key ] ) && isPlainObject ( val ) ) { result [ key ] = merge ( result [ key ] , val ) ; } else if ( isPlainObject ( val ) ) { result [ key ] = merge ( { } , val ) ; } else if ( isArray ( val ) ) { result [ key ] = val . slice ( ) ; } else { result [ key ] = val ; } } for ( let i = 0 , l = args . length ; i < l ; i ++ ) { forEach ( args [ i ] , assignValue ) ; } return result ; } export default { forEach , merge , isArray , } ;