Search code examples
javascriptoopobjectrecursion

Javascript Object Assignment Infinite recursion


I have an issue that I am struggling to grasp. Any help would be greatly appreciated.

I have an Object, and I assign the current object state to a property on the current object.

example below:

var product = {
  ropeType: 'blah',
  ropePrice: 'blah',
  ropeSections: {
    name: 'blaah',
    price: 'blaah'
  },
  memory: false
}

product.memory = product;

Now when I look at the product object within the console I get a inifinite recursion of Product.memory.Product.memory.Product....

screenshot below:

enter image description here

I know its something to do with that an object references itself, but I cannot seem to grasp the concept. Could someone explain?

The reason I am trying to do something like this is to save in local storage the current state of the object.

I hope I have made sense.


Solution

  • I assign the current object state to a property on the current object.

    No, you created a property that referred to itself.

    If you want to save the current state of the property then you need to clone the object.

    If you want to create a (shallow) copy of an object then you can use:

    function clone(obj) {
        if(obj === null || typeof(obj) !== 'object' || 'isActiveClone' in obj)
            return obj;
    
        var temp = obj.constructor();
    
        for(var key in obj) {
            if(Object.prototype.hasOwnProperty.call(obj, key)) {
                obj['isActiveClone'] = null;
                temp[key] = obj[key];
                delete obj['isActiveClone'];
            }
        }    
    
        return temp;
    }
    

    [code taken from here - and modified slightly to do a shallow copy rather than recursive deep copy]

    then do:

    product.memory = clone( product );
    

    You may find you get the issues with recursion if you clone it a second time and it copies the product.memory along with the rest of the object. In that case just delete product.memory before doing subsequent clones.

    Something like:

    function saveCurrentState( obj ){
      if ( 'memory' in obj )
        delete obj.memory;
       obj.memory = clone( obj );
    }
    

    Aside

    If you want a deep copy then you can do:

    function deepCopy(obj){
      return JSON.parse(JSON.stringify(obj));
    }
    

    [As suggested here - but note the caveats it has for Date objects]