Skip to content

Instantly share code, notes, and snippets.

@jfet97
Last active May 9, 2021 19:33
Show Gist options
  • Star 3 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save jfet97/b3bfca6a371c8954aa2d4f386d7cefb6 to your computer and use it in GitHub Desktop.
Save jfet97/b3bfca6a371c8954aa2d4f386d7cefb6 to your computer and use it in GitHub Desktop.
Using graph theory to clone JavaScript objects with circular references
function isObject(entity) {
return typeof entity === "object" && entity !== null;
}
function cloneNonObjectProperties(obj) {
return Object.fromEntries(
Object.entries(obj).filter(([, v]) => !isObject(v))
)
}
function getAdjacentNodes(obj) {
return (
Object.entries(obj)
.filter(([, v]) => isObject(v))
)
}
function cloneGraph(obj) {
return cloneNode(obj, new Map())
}
function cloneNode(obj, helperDict) {
// if we have already encountered this node
// we can just return its clone reference
if(helperDict.has(obj)) {
return helperDict.get(obj)
}
// otherwise we start by cloning non object properties
const clonedNode = cloneNonObjectProperties(obj);
// then we set the just cloned reference as the obj clone
// to avoid reworks on it
helperDict.set(obj, clonedNode)
// now we recursively clone each object reachable by the current node
for (const [k, n] of getAdjacentNodes(obj)) {
const clonedAdjacentNode = cloneNode(n, helperDict);
// we can set the new reference on the cloned obj
clonedNode[k] = clonedAdjacentNode
}
return clonedNode;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment