返回

面试题-浅拷贝与深拷贝

前端

什么是深拷贝和浅拷贝?

在JavaScript中,变量可以存储基本类型(字符串、数字、布尔值等)或引用类型(数组、对象等)。

基本类型的变量在赋值时,会将值直接复制给新变量。这意味着,对新变量进行任何更改都不会影响原始变量。

引用类型的变量在赋值时,会将引用复制给新变量。这意味着,对新变量进行任何更改都会影响原始变量。

let a = 10;
let b = a;

b = 20;

console.log(a); // 10
console.log(b); // 20

在这个示例中,ab都是基本类型的变量。当我们给b赋值20时,b的值被更改,但a的值没有被更改。这是因为ab都是独立的变量,它们各自存储自己的值。

let a = [1, 2, 3];
let b = a;

b[0] = 4;

console.log(a); // [4, 2, 3]
console.log(b); // [4, 2, 3]

在这个示例中,ab都是引用类型的变量。当我们给b[0]赋值4时,b的值被更改,a的值也被更改。这是因为ab指向同一个对象,因此对其中一个进行任何更改都会影响另一个。

如何实现深拷贝?

有几种方法可以实现深拷贝。一种方法是使用JSON.parse()JSON.stringify()方法。

let a = [1, 2, 3];
let b = JSON.parse(JSON.stringify(a));

b[0] = 4;

console.log(a); // [1, 2, 3]
console.log(b); // [4, 2, 3]

在这个示例中,我们使用JSON.stringify()方法将a转换为JSON字符串,然后使用JSON.parse()方法将JSON字符串转换为对象。这样,我们就创建了一个a的副本,这个副本与a完全独立。

另一种实现深拷贝的方法是使用递归。

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

  if (Array.isArray(obj)) {
    return obj.map(item => deepCopy(item));
  }

  const newObj = {};
  for (const key in obj) {
    newObj[key] = deepCopy(obj[key]);
  }

  return newObj;
}

let a = [1, 2, 3];
let b = deepCopy(a);

b[0] = 4;

console.log(a); // [1, 2, 3]
console.log(b); // [4, 2, 3]

在这个示例中,我们使用递归函数deepCopy()来实现深拷贝。该函数首先检查对象是否为基本类型或null,如果是,则直接返回对象。如果对象是数组,则使用map()方法对数组中的每个元素进行深拷贝。如果对象是对象,则使用for...in循环对对象中的每个键值对进行深拷贝。

深拷贝和浅拷贝在实际开发中都有各自的用处。浅拷贝可以提高程序的性能,而深拷贝可以确保数据的完整性。