How to convert sync and async recursive function to iteration in JavaScript How to convert sync and async recursive function to iteration in JavaScript node.js node.js

How to convert sync and async recursive function to iteration in JavaScript


In order for us to convert a procedure with a function that calls out to another function (whether or not it's the same function, aka 'recursive', makes no difference), we will need to separate it into the procedure that occurs before such a call and any procedures subsequent to the call. If there are no procedures after the out-call and the out-call is to the same function, we can describe it as "tail recursive," which can make the conversion to iterative much much simpler, simply pushing the call parameters to the stack (Example). In fact, converting tail-recursion to an iterative stack process has helped me overcome browsers' recursion-depth limits in more than one real instance.

Converting to tail-recursive

In order to convert a recursion to tail-recursive, we must consider how the information delivered from the recursive call is processed and whether we can transform this process to utilize parameters in the recursion itself. Since in your particular example, the only thing that happens with the out-call result is the setting of the local variable, output, and output is an object, which in JavaScript is passed by reference, we are in a position to make this transformation. So here's a simple refactor that will enable us to use a succinct stack (I skipped over the tail-recursive code to the stack implementation; left as an exercise for the reader):

var references = {}var object = {  a: {    b: {      c: {        d: {          e: 10,          f: 11,          g: 12        }      }    }  }}object.a.b.c.d.x = objectobject.a.b.c.d.y = object.a.bvar id = 1//var x = circularReferences(object, references)//console.log(x)//function circularReferences(object, references) {// => add parameters, 'output' and 'key'var stack = [[object, references, null, null]];while (stack.length){  [_object, _references, _callerOutput, _key] = stack.pop()  var output = {}    if (_object.__circularid__){    _callerOutput[_key] = '[Circular]'        // Log our example    console.log('OUTPUT VALUE: ' + JSON.stringify(_callerOutput))        // Exit    continue;  }    Object.defineProperty(_object, '__circularid__', { value: id++ })    for (var key in _object) {    var value = _object[key]        if (value && typeof value == 'object') {      console.log(value)            //var is = circularReferences(value, references)      // if (is) output[key] = '[Circular]'      stack.push([value, _references, output, key])            } else {      output[key] = value    }  }}