The proper way to do something like this should be to store the shared reference object separately and reference it using an identifier.
For example, you can hold importantProperty objects in an array and use the index as an identifier:
var importantProperties = [ { s: 1 }, { s: 2 }, { s: 3 } ]; var obj = {}; obj.importantProperty = importantProperties[1]; obj.c = obj.importantProperty; obj.d = obj.importantProperty;
Then, when you gate the object, you replace the reference object with its index:
var stringified = JSON.stringify(obj, function(key, value) { if (key) { return importantProperties.indexOf(value); } return value; }); console.log(stringified);
And then when you analyze, you just change the process to animate the links:
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);
Now the example above works for your code example under the assumption that all properties in obj are objects from the importantProperties array. If this is not the case, and these are only certain properties that are importantProperties objects, you need to check this when replacing / restoring.
Assuming these objects are the properties "importantProperty", "c" and "d":
if (['importantProperty', 'c', 'd'].includes(key)) instead of if (key)
If this is not enough and you do not want the property name to have anything to do with whether this value is an importantProperties object, you need to specify this value along with the identifier. Here is an example of how this can be done:
// 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; });