返回

揭开JS深克隆与浅克隆的神秘面纱,解析复制对象的真谛

前端

浅克隆:浮光掠影,触及表面

浅克隆是一种相对简单快捷的对象复制方式,它仅复制对象自身的属性,而不会复制其嵌套对象或数组。换言之,浅克隆的对象与原始对象共享对嵌套对象或数组的引用。

###浅克隆的实现原理

在JavaScript中,浅克隆可以通过简单的赋值运算符(=)或Object.assign()方法来实现。

赋值运算符(=)

const originalObject = {
  name: 'John Doe',
  age: 30,
  address: {
    street: 'Main Street',
    city: 'Anytown',
    state: 'CA',
  },
};

const clonedObject = originalObject;

上述代码使用赋值运算符(=)将originalObject的值赋给clonedObject。此时,clonedObject和originalObject指向同一个内存地址,因此它们共享相同的属性和值。如果对clonedObject的属性进行修改,则originalObject的属性也会随之改变,反之亦然。

Object.assign()方法

const originalObject = {
  name: 'John Doe',
  age: 30,
  address: {
    street: 'Main Street',
    city: 'Anytown',
    state: 'CA',
  },
};

const clonedObject = Object.assign({}, originalObject);

Object.assign()方法可以将一个或多个源对象的属性复制到目标对象。在上述代码中,Object.assign()方法将originalObject的属性复制到clonedObject中。此时,clonedObject和originalObject是两个独立的对象,它们具有相同的属性和值,但不会相互影响。

###浅克隆的使用场景

浅克隆主要适用于以下场景:

  • 需要对简单对象进行快速复制时。
  • 需要对对象进行浅层次的修改时。
  • 需要将对象作为函数参数传递时。

##深克隆:抽丝剥茧,深入本质

与浅克隆相比,深克隆是一种更为彻底的对象复制方式,它不仅复制对象自身的属性,还会递归地复制其嵌套对象或数组。换言之,深克隆的对象与原始对象没有任何共享的引用,它们是完全独立的个体。

###深克隆的实现原理

在JavaScript中,深克隆可以通过JSON.parse(JSON.stringify(obj))或递归算法来实现。

JSON.parse(JSON.stringify(obj))

const originalObject = {
  name: 'John Doe',
  age: 30,
  address: {
    street: 'Main Street',
    city: 'Anytown',
    state: 'CA',
  },
};

const clonedObject = JSON.parse(JSON.stringify(originalObject));

上述代码使用JSON.stringify()方法将originalObject转换为JSON字符串,然后再使用JSON.parse()方法将JSON字符串解析为对象。此时,clonedObject和originalObject是两个独立的对象,它们具有相同的属性和值,但不会相互影响。

递归算法

function deepClone(obj) {
  if (typeof obj === 'object' && obj !== null) {
    if (Array.isArray(obj)) {
      return obj.map(item => deepClone(item));
    } else {
      const clonedObject = {};
      for (const key in obj) {
        clonedObject[key] = deepClone(obj[key]);
      }
      return clonedObject;
    }
  } else {
    return obj;
  }
}

const originalObject = {
  name: 'John Doe',
  age: 30,
  address: {
    street: 'Main Street',
    city: 'Anytown',
    state: 'CA',
  },
};

const clonedObject = deepClone(originalObject);

上述代码使用递归算法实现深克隆。该算法首先检查obj的类型,如果是对象或数组,则递归地复制其内部元素;如果是基本类型,则直接返回。通过这种方式,可以实现对对象及其嵌套对象或数组的完全复制。

###深克隆的使用场景

深克隆主要适用于以下场景:

  • 需要对复杂对象进行完整复制时。
  • 需要对对象进行深度修改时。
  • 需要将对象存储在持久化存储中时。

##JS深克隆与浅克隆的比较

特征 浅克隆 深克隆
复制方式 仅复制对象自身的属性 递归地复制对象及其嵌套对象或数组
内存开销 较低 较高
执行速度 较快 较慢
应用场景 需要对简单对象进行快速复制时、需要对对象进行浅层次的修改时、需要将对象作为函数参数传递时 需要对复杂对象进行完整复制时、需要对对象进行深度修改时、需要将对象存储在持久化存储中时

##案例分析

为了更好地理解JS深克隆与浅克隆的区别,我们来看一个实际的案例。假设我们有一个数组,其中包含基本类型、对象和正则表达式。

const originalArray = [
  'John Doe',
  30,
  {
    street: 'Main Street',
    city: 'Anytown',
    state: 'CA',
  },
  new RegExp('^[a-zA-Z0-9]+
const originalArray = [
  'John Doe',
  30,
  {
    street: 'Main Street',
    city: 'Anytown',
    state: 'CA',
  },
  new RegExp('^[a-zA-Z0-9]+$'),
];
#x27;
), ];

如果我们使用浅克隆来复制这个数组,则会得到以下结果:

const clonedArray = originalArray.slice();

此时,clonedArray和originalArray指向同一个内存地址,因此它们共享相同的元素。如果对clonedArray的元素进行修改,则originalArray的元素也会随之改变,反之亦然。

clonedArray[2].street = 'New Street';

console.log(originalArray[2].street); // 'New Street'

如果我们使用深克隆来复制这个数组,则会得到以下结果:

const clonedArray = JSON.parse(JSON.stringify(originalArray));

此时,clonedArray和originalArray是两个独立的数组,它们具有相同的元素,但不会相互影响。如果对clonedArray的元素进行修改,则originalArray的元素不会受到影响。

clonedArray[2].street = 'New Street';

console.log(originalArray[2].street); // 'Main Street'

通过这个案例,我们可以清楚地看到,浅克隆只复制对象自身的属性,而深克隆则复制对象及其嵌套对象或数组。在实际开发中,我们可以根据不同的场景选择合适的复制方式。