code: function walkImpl(root, traversalStrategy, beforeFunc, afterFunc, context, collectResults) {
      var visited = [];
      return (function _walk(value, key, parent) {
        // Keep track of objects that have been visited, and throw an exception
        // when trying to visit the same object twice.
        if (_.isObject(value)) {
          if (visited.indexOf(value) >= 0) throw new TypeError(notTreeError);
          visited.push(value);
        }
  
        if (beforeFunc) {
          var result = beforeFunc.call(context, value, key, parent);
          if (result === stopWalk) return stopWalk;
          if (result === stopRecursion) return;
        }
  
        var subResults;
        var target = traversalStrategy(value);
        if (_.isObject(target) && !_.isEmpty(target)) {
          // If collecting results from subtrees, collect them in the same shape
          // as the parent node.
          if (collectResults) subResults = _.isArray(value) ? [] : {};
  
          var stop = _.any(target, function(obj, key) {
            var result = _walk(obj, key, value);
            if (result === stopWalk) return true;
            if (subResults) subResults[key] = result;
          });
          if (stop) return stopWalk;
        }
        if (afterFunc) return afterFunc.call(context, value, key, parent, subResults);
      })(root);
    }
docs: Walk the tree recursively beginning with `root`, calling `beforeFunc` before visiting an objects descendents, and `afterFunc` afterwards. If `collectResults` is true, the last argument to `afterFunc` will be a collection of the results of walking the node's subtrees.