[Interview Question] Deep and shallow copy in JavaScript: Principle and Implementation

Dachang interview questions share interview question bank

Front-end and back-end interview question banks (necessary for interviews) Recommended: ★★★★★

Address: front-end interview question bank   web front-end interview question bank VS java back-end interview question bank Daquan

foreword

  在开发过程中,我们经常会遇到需要复制一个对象或数组的情况。在 JavaScript 中,我们可以使用浅拷贝或深拷贝来实现复制功能。浅拷贝只会复制对象或数组的第一层属性,如果属性的值还是对象或数组,那么它们之间的引用关系并不会改变。相反,深拷贝会完全复制对象或数组的所有属性,并创建新的引用关系。

  在什么情况下需要使用深拷贝呢?通常来说,当我们希望对象或数组的改变不影响原对象或数组时,就需要使用深拷贝。例如,我们可能希望在处理数据的过程中保留原始数据的副本,或者在修改一个对象的属性时不影响原对象。在本文中,我们将介绍 JavaScript 中的深拷贝方法,并给出使用深拷贝的示例代码。

复制代码

1. What exactly is deep and shallow copy???

  在 JavaScript 中,对象和数组都是引用类型,它们的值是存储在内存中的地址,而不是实际的值。当我们复制一个对象或数组时,如果我们只是复制它们的地址,那么原来的对象或数组和新的对象或数组都指向同一个地址,对其中一个对象或数组的修改会影响另一个对象或数组。这种复制方式称为浅拷贝。为了避免这种情况,我们需要进行深拷贝,即复制对象或数组的值,而不是复制地址。
复制代码

2. Realization of deep copy

 深拷贝的方法有很多种,常见的方法包括使用 `JSON.parse` 和 `JSON.stringify`、使用递归算法、使用 lodash 等。
复制代码

2.1 Using JSON.parse and  JSON.stringify making deep copies

The method of using  JSON.parse and  JSON.stringify performing deep copy is very simple, you only need to convert the object or array to be copied  JSON.stringify into a string, and then use it  JSON.parse to convert the string back to the original object or array.

Here is a simple example showing how to use  JSON.parse and  JSON.stringify make a deep copy:

const original = { a: 1, b: { c: 2 } };

// 使用 JSON.stringify 将对象转化为字符串,再使用 JSON.parse 将字符串转回对象
const copy = JSON.parse(JSON.stringify(original));

console.log(original === copy); // false
console.log(original.b === copy.b); // false
复制代码

In this example, we first define an object containing nested objects  original, and then use  JSON.parse and  JSON.stringify deep copy to get a new object  copy. Finally, we use  === operators to compare whether the two objects are equal, and whether the nested objects of the two objects are equal, and find that the two objects and the two nested objects are not equal, indicating that a deep copy has been made.

2.2 Using recursive algorithm to realize deep copy

  使用 `JSON.parse` 和 `JSON.stringify` 进行深拷贝也有一些限制,比如不能复制函数、Symbol 等类型的值,也不能正确地复制循环引用的对象。

  因此,在实际应用中,我们还需要考虑使用其他的深拷贝方法来解决这些限制,例如递归算法实现深拷贝,它可以递归地复制对象或数组的值,并判断是否为基本类型(如数字、字符串、布尔值等),如果是基本类型就直接返回,否则就继续递归复制。
复制代码

The following is an example of implementing a deep copy using a recursive algorithm:

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

  // 判断是数组还是对象
  const isArray = Array.isArray(obj);
  const copy = isArray ? [] : {};

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

  return copy;
}

const original = { a: 1, b: { c: 2 } };
const copy = deepCopy(original);

console.log(original === copy); // false
console.log(original.b === copy.b); // false
复制代码

In this example, we define a  deepCopy function named , which takes an object or array as an argument, and makes a deep copy. First, we use  typeof operators to determine whether the incoming parameter is an object or an array, and return it directly if not. Then, we use  Array.isArray the function to determine whether the incoming parameter is an array or an object, and create a new array or object. Finally, we use a loop to iterate over the properties of an object or array and use recursion to call  deepCopy a function to copy the value of the property.

The method of using a recursive algorithm to implement deep copy is relatively complicated, but it has an obvious advantage, that is, it can correctly copy values ​​of types such as functions, Symbols, and circularly referenced objects.

2.2 What should be paid attention to when using deep copy?

  1. Issues related to the type of raw data

When using deep copy, we should pay attention that some types of data may change after being deep copied. For example, using  JSON.parse() the and  JSON.stringify() function converts the function to a string, while using a recursive function converts the regular expression to an empty object.

  1. Issues related to shallow copy

In some cases, we want some properties of objects or arrays not to be deep copied, but to use shallow copy. This can be achieved with a custom recursive function. For example, a blacklist can be set to indicate which attributes do not require deep copying.

3. Implementation of shallow copy

Shallow copy means that when copying an object or array, only its first-level attributes are copied, and the value of its attributes is not copied (if the value of the attribute is still an object or array). Therefore, there is still a reference relationship between the new object or array obtained by shallow copy and the original object or array .

In JavaScript, we can use the following methods to achieve shallow copy:

  • Using the spread operator ( ...): let newArray = [...oldArray],let newObject = {...oldObject}
  • Use  Object.assign() function:let newObject = Object.assign({}, oldObject)
  • Functions that work with arrays  slice() or functions with objects  Object.keys() : let newArray = oldArray.slice(),let newObject = Object.keys(oldObject).reduce((acc, key) => ({...acc, [key]: oldObject[key]}), {})

3.1 Application Scenarios of Shallow Copy

  与深拷贝相比,浅拷贝的实现方法要简单得多,但是它的功能也相对较弱。如果我们希望复制对象或数组的所有属性,并创建新的引用关系,还是需要使用深拷贝,但是在某些情况下,我们可能希望使用浅拷贝。
复制代码
  • When we need to construct a new object or array, we may wish to use a shallow copy. Because the shallow copy only copies the first-level attributes, it can save time and space for copying. For example, we can use a shallow copy to create a new array that contains all the elements of the original array, but does not contain any properties of the original array.

  • Shallow copy can also be used when we wish to copy some properties of an object or array. For example, we can use the spread operator or  Object.assign() function to copy some properties of an object. This saves copying time and space, because we only copy the properties that are needed.

In short, shallow copy is very useful in some specific scenarios, but its function is relatively weak. We should choose to use shallow copy according to the actual situation

3.2 Implementation method of shallow copy

Here are a few common methods:

  1. Use the spread operator (...):
function shallowClone(obj) {
  return {...obj};
}
复制代码
  1. Use  Object.assign() function:
function shallowClone(obj) {
  return Object.assign({}, obj);
}
复制代码
  1. Use the built-in constructor:
function shallowClone(obj) {
  if (obj === null || typeof obj !== 'object') {
    return obj;
  }
  let clone = new obj.constructor();
  for (let key in obj) {
    clone[key] = obj[key];
  }
  return clone;
}

let obj = {a: 1, b: 2, c: [3, 4, 5]};
let shallow = shallowClone(obj);
console.log(shallow); // {a: 1, b: 2, c: [3, 4, 5]}
复制代码

4. Summary

最后,在使用深浅拷贝时,我们要根据实际的需求来决定使用哪种方法,并确保复制的对象或数组能够满足我们的需求。
复制代码

If it is helpful, please give me a like, and please point out if there are any mistakes. I am CoderBug, a young man who is chasing after the wind like you!

Dachang interview questions share interview question bank

Front-end and back-end interview question banks (necessary for interviews) Recommended: ★★★★★

Address: front-end interview question bank   web front-end interview question bank VS java back-end interview question bank Daquan

 

Guess you like

Origin blog.csdn.net/weixin_42981560/article/details/130136418