Skip to content

Latest commit

 

History

History
77 lines (51 loc) · 2.52 KB

File metadata and controls

77 lines (51 loc) · 2.52 KB

63. create _.cloneDeep()

Problem

https://bigfrontend.dev/problem/create-cloneDeep

Problem Description

Object.assign() could be used to do shallow copy, while for recursive deep copy, _.cloneDeep could be very useful.

Can you create your own _.cloneDeep()?

The lodash implementation actually covers a lot of data types, for simplicity, your code just need to cover

  1. primitive types and their wrapper Object
  2. Plain Objects (Object literal) with all enumerable properties
  3. Array

Understanding the problem

Write a function that creates a deep clone of a value. The function should handle primitive types, Object literal and Array.

Approach

First, check the data type of the source data, return the source if it is a primitive or null. Depending the data type of the source, either create an empty array or an empty object to store the cloned value. Get all enumerable properties of the source including all symbol properties. Loop over the properties. For each property, recursively call the function with property value as argument; create the property in the cloned object/array and set its value to the result of the recursive call.

🙋‍♀️🙋‍♂️ In the initial attempt, I didn't handle the circular reference. We can use a WeakMap to store the source and its copy. If the source object is already in the WeakMap, return its corresponding copy instead of recursing further.

Solution

// Use WeakMap that stores cloned results to handle circular reference.
const cachedResult = new WeakMap();

function cloneDeep(data) {
  if (data === null || data === undefined) {
    return data;
  }

  if (typeof data !== 'object') {
    return data;
  }

  // If the source object is already in the WeakMap,
  // its corresponding copy is returned instead of recursing
  // further.
  if (cachedResult.has(data)) {
    return cachedResult.get(data);
  }

  const clone = Array.isArray(data) ? [] : {};
  // Store the source object and its clone in the WeakMap.
  cachedResult.set(data, clone);

  const keys = [
    ...Object.getOwnPropertyNames(data),
    ...Object.getOwnPropertySymbols(data),
  ];
  for (const key of keys) {
    clone[key] = cloneDeep(data[key]);
  }

  return clone;
}

Reference

Javascript Deep Clone Object with Circular References