Copying Arrays and Objects in JavaScript Without References

Sh Raj - Jun 18 - - Dev Community

Comprehensive Guide to Copying Arrays and Objects in JavaScript Without References

In JavaScript, copying arrays and objects can be tricky due to the nature of references. When you assign an array or object to a new variable, you're actually assigning a reference to the original data, not a copy. This means that changes to the new variable affect the original data. To avoid this, you need to create a true copy of the array or object. Here's a detailed guide on how to do this using various methods.

Copying Arrays

1. Using the Spread Operator

The spread operator (...) is a concise way to create a shallow copy of an array.

const originalArray = [1, 2, 3];
const copiedArray = [...originalArray];
Enter fullscreen mode Exit fullscreen mode
2. Using Array.prototype.slice

The slice method can be used to create a shallow copy of an array.

const originalArray = [1, 2, 3];
const copiedArray = originalArray.slice();
Enter fullscreen mode Exit fullscreen mode
3. Using Array.from

The Array.from method creates a new, shallow-copied array from an array-like or iterable object.

const originalArray = [1, 2, 3];
const copiedArray = Array.from(originalArray);
Enter fullscreen mode Exit fullscreen mode
4. Using concat Method

Using the concat method with an empty array also creates a shallow copy.

const originalArray = [1, 2, 3];
const copiedArray = [].concat(originalArray);
Enter fullscreen mode Exit fullscreen mode
5. Using structuredClone Method

The structuredClone method creates a deep copy of arrays, handling complex structures.

const originalArray = [1, 2, 3, [4, 5]];
const copiedArray = structuredClone(originalArray);
Enter fullscreen mode Exit fullscreen mode

For more details, refer to the MDN documentation on structuredClone.

Copying Objects

1. Using the Spread Operator

The spread operator can also be used to create a shallow copy of an object.

const originalObject = { a: 1, b: 2 };
const copiedObject = { ...originalObject };
Enter fullscreen mode Exit fullscreen mode
2. Using Object.assign

The Object.assign method copies all enumerable own properties from one or more source objects to a target object.

const originalObject = { a: 1, b: 2 };
const copiedObject = Object.assign({}, originalObject);
Enter fullscreen mode Exit fullscreen mode
3. Using JSON.parse and JSON.stringify

For a deep copy, where nested objects and arrays are also copied, you can use JSON.parse and JSON.stringify. This method does not work well with functions and undefined values.

const originalObject = { a: 1, b: { c: 2 } };
const copiedObject = JSON.parse(JSON.stringify(originalObject));
Enter fullscreen mode Exit fullscreen mode
4. Using structuredClone Method

The structuredClone method creates a deep copy of objects, supporting nested structures and circular references.

const originalObject = { a: 1, b: { c: 2 } };
const copiedObject = structuredClone(originalObject);
Enter fullscreen mode Exit fullscreen mode

For more details, refer to the MDN documentation on structuredClone.

Deep Copying with Custom Functions

For more complex objects, including those with nested structures, dates, and functions, you might need a custom deep copy function.

1. Recursive Function for Deep Copy

Here's a basic recursive function to perform a deep copy of an object.

function deepCopy(obj) {
  if (obj === null || typeof obj !== 'object') return obj;

  if (Array.isArray(obj)) {
    const arrCopy = [];
    for (let i = 0; i < obj.length; i++) {
      arrCopy[i] = deepCopy(obj[i]);
    }
    return arrCopy;
  }

  const objCopy = {};
  for (const key in obj) {
    if (obj.hasOwnProperty(key)) {
      objCopy[key] = deepCopy(obj[key]);
    }
  }
  return objCopy;
}

const originalObject = { a: 1, b: { c: 2 } };
const copiedObject = deepCopy(originalObject);
Enter fullscreen mode Exit fullscreen mode

Libraries for Deep Copying

Several libraries provide robust and efficient deep copy functionality, handling edge cases and complex data structures.

1. Lodash

Lodash is a popular utility library that includes a cloneDeep function for deep copying.

const _ = require('lodash');
const originalObject = { a: 1, b: { c: 2 } };
const copiedObject = _.cloneDeep(originalObject);
Enter fullscreen mode Exit fullscreen mode
2. DeepClone

The deepClone library is specifically designed for deep copying objects.

const deepClone = require('deepClone');
const originalObject = { a: 1, b: { c: 2 } };
const copiedObject = deepClone(originalObject);
Enter fullscreen mode Exit fullscreen mode

Conclusion

Copying arrays and objects in JavaScript without maintaining references is crucial for preventing unintended side effects. For simple, shallow copies, the spread operator and methods like slice, Array.from, and Object.assign are effective. For deep copies, structuredClone provides a modern and robust solution, while JSON.parse with JSON.stringify works for many cases. Custom functions or libraries like Lodash may be necessary for complex structures. By understanding and using these methods, you can ensure your data manipulation is both efficient and safe.

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .