执行此类操作的正确方法是单独存储公共引用对象并通过 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 (['importantProperty', 'c', 'd'].includes(key)) 而不仅仅是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;
});