【问题标题】:How to copy json object without reference in vue?如何在vue中复制没有引用的json对象?
【发布时间】:2020-10-31 23:51:30
【问题描述】:

在我的组件中,我声明了一些这样的数据:

data() {
    return {
        defaultValue: {json object with some structure},
        activeValue: {}
        ...

并且在组件方法中复制这个值:

this.activeValue = this.defaultValue

但问题是,更改 this.activeValue 值后,this.defaultValue 也发生了变化。

如果我使用 Object.freeze(this.defaultValue) 并尝试更改 this.activeValue 我得到错误 - 对象不可写。

如何在没有参考的情况下复制数据?

【问题讨论】:

    标签: javascript json vue.js reference copy


    【解决方案1】:

    如果你有简单的对象,最快最简单的方法就是使用 JSON.parse 和 JSON.stringify;

    const obj = {};
    
    const objNoReference = JSON.parse(JSON.stringify(obj));
    

    【讨论】:

    • 注意,此方法将日期转换为字符串,不会复制Map等特殊类型
    【解决方案2】:
    this.activeValue = { ...this.defaultValue }
    

    如果您没有嵌套对象,使用 ES6 扩展运算符将帮助您进行复制。如果使用等号 = 相等,则不会创建新对象,只会创建一个引用当前对象的变量(如浅拷贝)。

    要做一个完整的深拷贝,即使它是嵌套对象,也可以这样做:

     const objNoReference = JSON.parse(JSON.stringify(obj));
    

    按照猫头鹰的建议。

    Click to read more for better understanding of the concept

    【讨论】:

    • 术语混淆。 { ...this.defaultValue } 不是解构而是扩展语法。它会创建一个浅拷贝而不是深拷贝 - 除非您使用 { ...this.defaultValue, foo: { ...this.defaultValue.foo } } 明确执行此操作。 = 通过引用复制,不进行浅复制。
    • @EstusFlask 你是对的,我编辑了我的答案并理解如果我们使用扩展运算符,嵌套对象将是浅拷贝。
    • JSON 方法删除了 MapRegex 等数据类型以及 stringfy Date 很可能导致错误
    【解决方案3】:

    JSON.stringify 比使用 JSON.parse 更好的方法是:

    this.activeValue = {...this.defaultValue}
    

    但某些浏览器 (IE) 本身并不支持此功能,除非与转译器 (babel) 一起使用

    https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Spread_syntax

    更新

    考虑到您最初的问题是关于 Vue 中的一种方式,vue 中也有一个本机方法:

    this.activeValue = Vue.util.extend({}, this.defaultValue)
    

    as for this answer.

    希望这会有所帮助!

    【讨论】:

    • 这会创建一个浅拷贝,并且不会像嵌套对象的预期那样工作。
    【解决方案4】:

    您可以使用 'JSON.parse and stringify' 或使用库中的一些克隆函数,例如 lodash(下划线、ramda...)

    【讨论】:

      【解决方案5】:

      对象是通过引用分配和复制的。

      所有通过复制引用的操作(如添加/删除属性)都在同一个对象上执行。

      要创建“real copy”(克隆),我们可以将Object.assign 用于所谓的“shallow copy”(嵌套对象通过引用复制)。

      对于“deep cloning”,使用来自loadash 库的_.cloneDeep(obj)。

      【讨论】:

        【解决方案6】:

        JSON stringify&pa​​rse 方法存在一些问题,例如将日期对象转换为字符串。它也不能处理特殊的数据类型,如MapSetfunction 等......这很容易在未来出现错误。

        我使用下面的方法来深拷贝一个对象。

        记住!这不是一个完整的克隆应用程序。还有更多数据类型需要处理,例如BlobRegExp 等...

          const deepClone = (inObject) => {
                    let outObject, value, key
        
                    if (typeof inObject !== "object" || inObject === null) 
                        return inObject
                    
                    if (inObject instanceof Map) {
                        outObject = new Map(inObject);
                        for ([key, value] of outObject)
                            outObject.set(key, deepClone(value))
                    } else if (inObject instanceof Set) {
                        outObject = new Set();
                        for (value of inObject)
                            outObject.add(deepClone(value))
                    } else if (inObject instanceof Date) {
                        outObject = new Date(+inObject)
                    } else {
                        outObject = Array.isArray(inObject) ? [] : {}
                        for (key in inObject) {
                            value = inObject[key]
                            outObject[key] = deepClone(value)
                        }
                    }
                    return outObject
                }
        

        【讨论】:

          【解决方案7】:

          还有一个简单的解决方案是将defaultValue: {json object with some structure}JSON.stringify(defaultValue) 存储在字符串变量中:

          var x = JSON.stringify(this.defaultValue);
          

          如果您再次需要它作为 JSON 对象,您可以使用 JSON.parse() 获取它:

          var newObject = JSON.parse(x);
          

          这样做也破坏了对象引用,如果对象defaultValue 的内容发生更改,x 将保持不变。

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 2011-05-06
            • 1970-01-01
            • 1970-01-01
            • 2018-08-05
            • 2015-02-22
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多