code: function(visitor, defaultValue, context) {
      var self = this;
      var memo = new WeakMap();
      function _visit(stack, value, key, parent) {
        if (isObject(value) && stack.indexOf(value) >= 0)
          throw new TypeError('A cycle was detected at ' + value);
  
        if (memo.has(value))
          return memo.get(value);
  
        var subResults;
        var target = self._traversalStrategy(value);
        if (isObject(target) && Object.keys(target).length > 0) {
          subResults = {};
          each(target, function(child, k) {
            defineEnumerableProperty(subResults, k, function() {
              return _visit(copyAndPush(stack, value), child, k, value);
            });
          });
        }
        var result = visitor.call(context, subResults, value, key, parent);
        memo.set(value, result);
        return result;
      }
      return function(obj) { return _visit([], obj); };
    }
docs: An 'attribute' is a value that is calculated by invoking a visitor function on a node. The first argument of the visitor is a collection of the attribute values for the node's children. These are calculated lazily -- in this way the visitor can decide in what order to visit the subtrees.