返回

底层逻辑剖析!了解数据在内存中的存放与原生JS深拷贝的原理

见解分享

众所周知,数据是计算机处理和存储的核心,而在计算机中,数据主要存储在内存中。内存分为代码空间、栈空间和堆空间三种类型,它们各自承担着不同的职责。

代码空间主要用来存储可执行代码,栈空间用来存放函数参数和局部变量,堆空间则用来存放动态分配的内存空间,例如对象和数组。

当我们在JavaScript中声明一个变量时,它的值会存储在栈空间或堆空间中。原始类型数据,如数字、字符串和布尔值,会直接存储在栈空间中;引用类型数据,如对象和数组,则会存储在堆空间中。

当我们对引用类型数据进行复制时,实际上是复制了指向该数据的指针,而不是复制数据本身。因此,如果我们对复制后的数据进行修改,也会影响到原始数据。这种复制方式称为浅拷贝。

如果我们想要真正地复制一个引用类型数据,我们需要使用深拷贝。深拷贝会递归地复制数据及其所有属性,从而创建一个新的数据对象,与原始数据完全独立。

在原生JavaScript中,我们可以使用Object.assign()方法来实现深拷贝。Object.assign()方法可以将一个或多个源对象的可枚举属性复制到目标对象。

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

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

copyObject.name = "Jane";
copyObject.address.street = "456 Elm Street";

console.log(originalObject);
// { name: 'John', age: 30, address: { street: '123 Main Street', city: 'Anytown', state: 'CA' } }

console.log(copyObject);
// { name: 'Jane', age: 30, address: { street: '456 Elm Street', city: 'Anytown', state: 'CA' } }

在上面的例子中,我们使用Object.assign()方法将originalObject复制到copyObject。然后,我们修改了copyObject的name和address.street属性。可以看到,originalObject并没有受到影响。

需要注意的是,Object.assign()方法只能复制可枚举的属性。如果一个属性是不可枚举的,那么它不会被复制。

如果我们想要复制一个不可枚举的属性,可以使用JSON.parse()和JSON.stringify()方法来实现。

const originalObject = {
  name: "John",
  age: 30,
  address: {
    street: "123 Main Street",
    city: "Anytown",
    state: "CA",
  },
  symbol: Symbol("secret"),
};

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

console.log(copyObject);
// { name: 'John', age: 30, address: { street: '123 Main Street', city: 'Anytown', state: 'CA' } }

在上面的例子中,我们使用JSON.parse()和JSON.stringify()方法将originalObject复制到copyObject。可以看到,copyObject中没有symbol属性,因为symbol属性是不可枚举的。

希望这篇文章对您理解数据在内存中的存放方式以及原生JS深拷贝的实现原理有所帮助。