Deep Cloning an Object
Fri May 03 2024
Base Cases:
The function checks if the object is null or not an object, in which case it simply returns the value, as primitive values and null do not need further processing.
Array Handling:
If the object is an array, the function creates a new array and recursively clones each element. To handle recursive structures, a Map is used to track previously seen objects.
Object Handling:
If the object is not an array but an object, a new object is created and each key-value pair is recursively cloned. The Map is again used to track seen objects, avoiding infinite loops in cases of recursive references.
Recursive Reference Handling:
Before deep cloning, the function checks if the object has already been seen (using the Map), and if so, returns the already cloned reference, preventing infinite loops.
1const company = {
2    name: "Tech Solutions",
3    departments: [
4        {
5            name: "Engineering",
6            employees: [
7                { name: "Alice", role: "Software Engineer" },
8                { name: "Bob", role: "DevOps Engineer" }
9            ],
10            subdepartments: [
11                {
12                    name: "Quality Assurance",
13                    employees: [
14                        { name: "Charlie", role: "QA Engineer" }
15                    ],
16                    subdepartments: []
17                }
18            ]
19        },
20        {
21            name: "Human Resources",
22            employees: [
23                { name: "David", role: "Recruiter" },
24                { name: "Eve", role: "Benefits Coordinator" }
25            ],
26            subdepartments: []
27        }
28    ]
29};
30
31
32function deepClone(obj, seen = new Map()) {
33    if (obj === null || typeof obj !== 'object') {
34        return obj;
35    }
36
37    if (Array.isArray(obj)) {
38        const newArray = [];
39        seen.set(obj, newArray);
40        for (const item of obj) {
41            newArray.push(deepClone(item, seen));
42        }
43        return newArray;
44    }
45
46    if (obj instanceof Object) {
47        if (seen.has(obj)) {
48            return seen.get(obj);
49        }
50
51        const newObj = {};
52        seen.set(obj, newObj);
53        for (const key in obj) {
54            if (obj.hasOwnProperty(key)) {
55                newObj[key] = deepClone(obj[key], seen);
56            }
57        }
58        return newObj;
59    }
60
61    return obj;
62}
63
64
65
66// Add recursive reference
67company.departments.push(company.departments[0]);
68
69const clonedCompany = deepClone(company);
70
71// Verify the deep clone
72console.log(clonedCompany);
73console.log(clonedCompany.departments[0] === clonedCompany.departments[1]); // should be true
74console.log(clonedCompany.departments[0] === company.departments[0]); // should be false
75
76
77
78
79// let deepObj = JSON.parse(JSON.stringify(company))
80// company["companies"] = ['Squbix', 'LDRexg']
81// console.log(deepObj);
82// console.log(company);
83
84// Possible addition for recursive reference testing
85company.departments.push(company.departments[0]);  // Intentional recursive link
86