【问题标题】:Deep Copying of a JavaScript Object not working when encapsulated within a VueJS computed property封装在 VueJS 计算属性中时,JavaScript 对象的深度复制不起作用
【发布时间】:2021-04-05 18:33:13
【问题描述】:

我在 Vue 实例中有一个 JavaScript 对象,它通过计算属性被深度复制到另一个 JavaScript 对象中。然而由于某种原因,它浅拷贝了有问题的对象而不是深拷贝,即使正在使用JSON.parse(JSON.stringify())

<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>

我正在尝试使用计算属性中的以下循环深度复制 formDialog.inputs 的值:

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;
    }  
  }
})

然而,obj 对象保留了this.formDialog.inputs 对象的浅拷贝,而我希望它对其进行深层拷贝。为什么即使我使用JSON.parse(JSON.stringify(obj)),它也没有创建对象的深层副本?

问题演示: https://codepen.io/deftonez4me/pen/qBapYgP

【问题讨论】:

  • 您认为这是浅拷贝的原因是什么?使用JSON.parse 从字符串创建新对象不可能导致浅拷贝。不是我不相信你,我肯定和你一样困惑。我只是好奇你是如何确认你的副本实际上很浅的。
  • 注意所有val属性值都是空字符串,所以调用JSON.parse(JSON.stringify(''))会返回空字符串,或者和浅拷贝一样的值...
  • obj 对象中的元素仍然保留对this.formDialog.inputs 元素的引用。当我修改this.formDialog.inputs 时,它也会修改obj 元素。

标签: javascript vue.js object deep-copy


【解决方案1】:

你应该试试这个:

    if (this.formDialog.hasOwnProperty('inputs')) {
        obj[key] = JSON.parse(JSON.stringify(this.formDialog.inputs));
    }

【讨论】:

    【解决方案2】:

    这里是您的代码的略删版本,我相信它会达到我们的目的:

    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)

    请注意,我已经对您的循环进行了更正,方法是在将 val 输入到 JSON.stringify 之前将其关闭。你提到了

    obj 对象中的元素仍然保留对 this.formDialog.inputs 元素的引用。当我修改 this.formDialog.inputs 时,它也会修改 obj 元素

    但恐怕这不是真的,正如您通过更改克隆对象的obj.id.val 所看到的那样,原始对象不受影响。

    因此,除了该调整之外,您的代码可以正常工作。也许您的特定环境会产生问题,因为您似乎确实在课堂上这样做。

    【讨论】:

    • 这对我也不起作用。这可能是我正在使用的框架特有的问题。它位于 vueJS 组件的计算属性中。我将创建一个 sn-p 并重新创建我正在开发它的环境。
    • 我为我所指的内容添加了一个 Codepen 演示。 codepen.io/deftonez4me/pen/qBapYgP
    猜你喜欢
    • 1970-01-01
    • 2021-11-08
    • 1970-01-01
    • 2010-11-23
    • 2013-11-27
    • 2020-04-13
    • 2012-07-03
    • 1970-01-01
    • 2015-01-08
    相关资源
    最近更新 更多