Detecting and fixing circular references in JavaScript

后端 未结 15 870
庸人自扰
庸人自扰 2020-11-28 23:29

Given I have a circular reference in a large JavaScript object

And I try JSON.stringify(problematicObject)

And the browser throws

15条回答
  •  夕颜
    夕颜 (楼主)
    2020-11-29 00:10

    This is a fix for both @Trey Mack and @Freddie Nfbnm answers on the typeof obj != 'object' condition. Instead it should test if the obj value is not instance of object, so that it can also work when checking values with object familiarity (for example, functions and symbols (symbols aren't instance of object, but still addressed, btw.)).

    I'm posting this as an answer since I can't comment in this StackExchange account yet.

    PS.: feel free to request me to delete this answer.

    function isCyclic(obj) {
      var keys = [];
      var stack = [];
      var stackSet = new Set();
      var detected = false;
    
      function detect(obj, key) {
        if (!(obj instanceof Object)) { return; } // Now works with other
                                                  // kinds of object.
    
        if (stackSet.has(obj)) { // it's cyclic! Print the object and its locations.
          var oldindex = stack.indexOf(obj);
          var l1 = keys.join('.') + '.' + key;
          var l2 = keys.slice(0, oldindex + 1).join('.');
          console.log('CIRCULAR: ' + l1 + ' = ' + l2 + ' = ' + obj);
          console.log(obj);
          detected = true;
          return;
        }
    
        keys.push(key);
        stack.push(obj);
        stackSet.add(obj);
        for (var k in obj) { //dive on the object's children
          if (obj.hasOwnProperty(k)) { detect(obj[k], k); }
        }
    
        keys.pop();
        stack.pop();
        stackSet.delete(obj);
        return;
      }
    
      detect(obj, 'obj');
      return detected;
    }
    

提交回复
热议问题