2017-06-21 75 views
5

我想深入克隆一个对象,用k = JSON.parse(JSON.stringify(a))说“a”。我使用stringify方式很重要,因为我试图将对象保存到文件中,然后从中加载。javaScript:使用JSON.parse解析字符串化对象,删除引用

我偶然发现与克隆的对象上的引用中的问题,其如下所示:

var obj={}; 
 
obj.importantProperty={s:2}; 
 
obj.c=obj.importantProperty; 
 
obj.d=obj.importantProperty; 
 
console.log(obj.c === obj.d); // Returns true 
 

 
var cloned = JSON.parse(JSON.stringify(obj)); 
 
console.log(cloned.c === cloned.d); // Returns false
我需要保持的参考文献中使用JSON.parse时,在上面的例子中它们是不。在我的项目中,对象更加复杂,但最终归结于上面的示例。

在此先感谢任何人谁帮助我这个:)

+3

'JSON.parse'创建一个从字符串表示一个新的结构。无法理解两个对象是相同的。 –

+0

甚至更​​多:'克隆=== obj - > false'。 –

+0

克隆=== obj - > false是正常的,因为克隆的对象是深克隆,即不同的引用。感谢您的回复。 –

回答

0

做这样的事情的正确方法是分别存储通用的引用对象并通过ID引用它。

举例来说,你可以在一个阵列握住你的importantProperty对象,并使用指数作为ID:

var importantProperties = [ 
    { s: 1 }, 
    { s: 2 }, 
    { s: 3 } 
]; 

var obj = {}; 
obj.importantProperty = importantProperties[1]; 
obj.c = obj.importantProperty; 
obj.d = obj.importantProperty; 

然后,当你字符串化的对象,你替换它的索引被引用的对象:

var stringified = JSON.stringify(obj, function(key, value) { 
    if (key) { 
    return importantProperties.indexOf(value); 
    } 
    return value; 
}); 
console.log(stringified); 
// prints {"importantProperty":1,"c":1,"d":1} 

然后当你分析你根本扭转这一进程,重振引用:

var parsed = JSON.parse(stringified, function(key, value) { 
    if (key) { 
    return importantProperties[value]; 
    } 
    return value; 
}); 
console.log(parsed.c === parsed.d && parsed.d === parsed.importantProperty); 
// prints true 

现在,上面的示例适用于您的示例代码,前提是obj中的所有属性都是importantProperties数组中的对象。如果情况并非如此,并且只有某些属性是importantProperties对象,则需要在更换/恢复时检查该对象。
假设只有“importantProperty”,“c”和“d”的属性是这样的对象:
​​,而不是仅仅if (key)

如果这还不够好,你不想要的属性名称有无论该值是否为importantProperties对象,您都需要在标识符中指定该值。这里有一个如何可以做到这一点的例子:

// Replacing 
JSON.stringify(obj, function(k, value) { 
    if (importantProperties.includes(value)) { 
    return 'ImportantProperty[' 
     + importantProperties.indexOf(value) 
     + ']'; 
    } 
    return value; 
}); 

// Reviving 
JSON.parse(stringified, function(k, value) { 
    if (/^ImportantProperty\[\d+\]$/.test(value)) { 
    var index = Number(value.match(/\d+/)[0]); 
    return importantProperties[index]; 
    } 
    return value; 
}); 
0

这是不可能实现的使用JSON你想要的结果,因为JSON格式可以只包含数据类型的有限ammount的(http://json.org/),当你的字符串化对象到JSON一些信息会丢失。

也许还有一些其他类型的序列化技术,但我会建议您寻找另一种方法来存储数据。