import isObject from './isObject' ; import DeepVisitBreak from './DeepVisitBreak' ; export interface ICallback { ( value , key , parentObject , keyPathList ) : DeepVisitBreak ; } function run ( obj , callback , keyPathList , visitedObjList ) { const visit = ( key ) : DeepVisitBreak => { const value = obj [ key ] ; const curKeyPathList = [ ... keyPathList , key ] ; if ( isObject ( value ) ) { if ( visitedObjList . indexOf ( value ) !== - 1 ) { callback ( value , key , obj , curKeyPathList ) ; return DeepVisitBreak . CHILDREN ; } visitedObjList . push ( value ) ; } const r = callback ( value , key , obj , curKeyPathList ) ; if ( r === DeepVisitBreak . ALL ) { return DeepVisitBreak . ALL ; } if ( r !== DeepVisitBreak . CHILDREN && run ( value , callback , curKeyPathList , visitedObjList ) === DeepVisitBreak . ALL ) { return DeepVisitBreak . ALL ; } return DeepVisitBreak . NO ; } ; if ( Array . isArray ( obj ) ) { for ( let i = 0 , il = obj . length ; i < il ; i += 1 ) { const visitResult = visit ( i ) ; if ( DeepVisitBreak . ALL === visitResult ) { return DeepVisitBreak . ALL ; } } } else if ( isObject ( obj ) ) { for ( const key in obj ) { const visitResult = visit ( key ) ; if ( DeepVisitBreak . ALL === visitResult ) { return DeepVisitBreak . ALL ; } } } return DeepVisitBreak . NO ; } param obj param callback export default function deepVisit ( obj , callback ) { run ( obj , callback , [ ] , [ obj ] ) ; }