-2

I have a JavaScript object in a Vue instance that is being deep copied into another JavaScript object via a computed property. However for some reason it shallow copies the object in question instead of a deep copy, even though JSON.parse(JSON.stringify()) is being used:

<div id="app">
  <v-app id="inspire">
    <v-row>
      <v-col cols="6">
        <v-text-field 
          v-model="formDialog.inputs.definition.val" 
          placeholder="Definition from FormDialog"></v-text-field>  
      </v-col>  
      <v-col cols="6">
        <v-text-field 
          v-model="initFields.definition" 
          placeholder="Definition from Init Fields"></v-text-field>
      </v-col>
    </v-row>
    
    <v-row>
      <v-col cols="6">
        <v-text-field 
          v-model="formDialog.inputs.synonym.val" 
          placeholder="Synonym from FormDialog"></v-text-field>
      </v-col>  
      <v-col cols="6">
        <v-text-field 
          v-model="initFields.synonym" 
          placeholder="Synonym from Init Fields"></v-text-field>
      </v-col>
    </v-row>
   
  </v-app>
</div>

I am attempting to deep copy the value of formDialog.inputs using the following loop within a compupted property:

new Vue({
  el: '#app',
  vuetify: new Vuetify(),
  data () {
    return {
      formDialog: {
                    inputs: {
                        definition: {
                            val: '', save: true, add: true,
                            icon: 'mdi-file-word',
                            placeholder: 'Word Definition'
                        },

                        synonym: {
                            val: '', save: true, add: true,
                            placeholder: 'Synonyms'
                        }
                    }
                }
    }
  },
  computed: {
    initFields: function() {
      let obj = {};
      if(typeof this.formDialog.inputs != 'undefined') {
        for(let key of Object.keys(this.formDialog.inputs)) {
          if(typeof this.formDialog.inputs[key].val != 'undefined') {
            //obj[key] = JSON.parse(JSON.stringify(this.formDialog.inputs[key]));
            obj[key] = this.formDialog.inputs[key].val;
          }
        }
      }

      return JSON.parse(JSON.stringify(obj));
      //return obj;
    }  
  }
})

However the obj object is retaining a shallow copy of the this.formDialog.inputs object, when I expect it to make a deep copy of it. Why is it not creating a deep copy of the object even though I am using JSON.parse(JSON.stringify(obj))?

Demonstration of issue: https://codepen.io/deftonez4me/pen/qBapYgP

  • 3
    What is your reasoning that this is a shallow copy? Creating a new object from a string using `JSON.parse` could not possibly lead to a shallow copy. Not that I not believe you, I would be as baffled as you, I'm sure. I'm just curious how you confirm that your copy is actually shallow. – ippi Dec 29 '20 at 03:26
  • 1
    Note that all of the `val` property values are the empty string, so calling `JSON.parse(JSON.stringify(''))` returns the empty string, or the same value as a shallow copy... – Heretic Monkey Dec 29 '20 at 03:31
  • The elements in the `obj` object are still retaining the reference to the elements of `this.formDialog.inputs`. When I modify `this.formDialog.inputs` it also modifies the `obj` elements. – VerySeriousSoftwareEndeavours Dec 29 '20 at 03:41

2 Answers2

0

Here is a somewhat abridged version of your code, which, I believe will serve our purpose:

const formDialog = {
    inputs: {
        id: {
            val: '',
            save: true,
        },

        word_data: [],

        definition: {
            val: '',
                save: true, add: true,
                icon: 'mdi-file-word',
                placeholder: 'Word Definition'
        },

        synonym: {
            val: '', save: true, add: true,
                placeholder: 'Synonyms'
        }
    }
}

let obj = {};
for(let key of Object.keys(formDialog.inputs)) {
    if(typeof formDialog.inputs[key].val !== 'undefined') {
        //why is this line making a shallow copy and not a deep copy?
        obj[key] = JSON.parse(JSON.stringify(formDialog.inputs[key]));
    }
}

obj.id.val = 'zunit';

console.log(obj);

console.log(formDialog)

Notice that I have made a correction to your loop by knocking off the val before feeding it into JSON.stringify. You mention that

The elements in the obj object are still retaining the reference to the elements of this.formDialog.inputs. When I modify this.formDialog.inputs it also modifies the obj elements

But I'm afraid that's not true as you will see by changing obj.id.val of the cloned object, the original object is unaffected.

So outside of that tweak, your code works fine. Perhaps your specific environment creates the issue as you do appear to be doing this inside a class.

codemonkey
  • 7,325
  • 5
  • 22
  • 36
-1

You should try this:

    if (this.formDialog.hasOwnProperty('inputs')) {
        obj[key] = JSON.parse(JSON.stringify(this.formDialog.inputs));
    }
Vikram Kumar
  • 3,876
  • 1
  • 17
  • 28