简体   繁体   English

是否可以非递归方式遍历JavaScript中的对象?

[英]Is it possible to traverse object in JavaScript in non-recursive way?

For example we have a JavaScript object which can contain other objects with arbitrary depth of nesting. 例如,我们有一个JavaScript对象,它可以包含具有任意嵌套深度的其他对象。 Is it possible to traverse every element of this object not using recursion? 是否可以不使用递归遍历此对象的每个元素?

If not then what are minimum requirement for data structure to make it traversal using non-recursive iteration? 如果不是,那么使用非递归迭代对数据结构进行遍历的最低要求是什么?

As SLaks wrote above any recursion can be represented as loop with stack. 正如SLaks在上面所写,任何递归都可以表示为堆栈循环。 So after thinking a while I came up with next solution: 因此,考虑了一会儿之后,我想到了下一个解决方案:

var myobj = {
    one: "hello",
    two: "world",
    three: {
        one: 1,
        two: 2,
        three: 4,
        four: {
            one: true,
            two: false
        }
    },
    four: "!"
};

function traverse(obj) {
    var stack = [];

    stack.push(obj);

    while (stack.length) {
        for (var j in stack[0]) {
            if (typeof stack[0][j] === 'object') {
                stack.push(stack[0][j]);
            } else {
                console.log('%s: %s', j, stack[0][j]);
            }
        }
        stack.shift();
    }
}

traverse(myobj);

Traversing arbitrary object requires support for primitive types as well as complex types (including arrays), as well as protection against cyclic references. 遍历任意对象需要对原始类型和复杂类型(包括数组)的支持,以及对循环引用的保护。 The following is a sample non recursive function that should traverse and stringify any object: 以下是示例非递归函数,该函数应遍历和字符串化任何对象:

function FlatStringify( Arg )
{
   var ToString = '', ArgObject, Resume, nStartIndex, Stack = [], Processed = []

   do
   {
      if( Array.isArray( Arg ) )
      {
         var nIndex, nLen = Arg.length

         if( Resume )
         {
            nStartIndex = Resume[1] + 1
            ArgObject = Resume[2]
            Resume = undefined

            if( nStartIndex < nLen )
            {
               ToString += ', '
            }
         }
         else
         {
            if( Processed.indexOf( ArgObject ? ArgObject : Arg ) >= 0 )
            {
               ToString += '{ <cyclic>'
               nStartIndex = nLen
            }
            else
            {
               Processed.push( ArgObject ? ArgObject : Arg )
               nStartIndex = 0
               ToString += '{'
            }
         }

         nIndex = nStartIndex
         if( nIndex < nLen )
         {
            // Save our Array and loop position
            Stack.push( [ Arg, nIndex, ArgObject ] )

            // Restore Object Context if any!
            if( ArgObject )
            {
               ToString += ' ' + Arg[ nIndex ] + ': '
               Arg = ArgObject[ Arg[ nIndex ] ]
            }
            else
            {
               ToString += ' '
               Arg = Arg[ nIndex ]
            }

            nIndex++
         }

         if( nIndex >= nLen )
         {
            ToString += ' }'
            ArgObject = undefined
         }
         else
         {
            // Skip to the while( ... )
            continue
         }
      }
      else if( typeof Arg === 'object' )
      {
        if( Arg == null )
        {
           ToString += 'null'
        }
        else
        {
           ArgObject = Arg
           Arg = Object.keys( ArgObject )
           continue
        }
     }
     else if( typeof Arg === 'string' )
     {
        ToString += "'" + Arg + "'"
     }
     else if( typeof Arg === 'function' )
     {
        ToString += 'function ' +  Arg.name + '(){...}'
     }
     else if( typeof Arg === 'number' )
     {
        ToString += Arg
     }
     else if( typeof Arg === 'boolean' )
     {
        ToString += Arg
     }
     else
     {
        //console.log( typeof Arg )
        ToString += typeof Arg//String( Arg )
     }

     if( Stack.length )
     {
        //console.log( 'Resuming: ' + Stack.length + '(' + nLoops + ')' )
        Resume = Stack.pop()
        Arg = Resume[0]
     }
   }
   while( Resume || ArgObject || Stack.length )

   return ToString
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM