JavaScript随记-深拷贝-vs-浅拷贝

33次阅读

共计 749 个字符,预计需要花费 2 分钟才能阅读完成。

在 ES6 的系列文章中,基本都会提到 Spread——扩展运算符(...) 的使用。伴随着这个运算符的出现,也往往会牵扯出其他一些问题,深拷贝 浅拷贝 就是其中之一。

相关背景

在讨论 深拷贝 浅拷贝 之前,我们先看一个例子:

let a = 'hi';
b = a;
b = 'hello';
console.log(a);
// 'hi'

let arr1 = [1,2,3];
arr2 = arr1;
arr2[0] = 0;
console.log(arr1);
// [0,2,3]

可以看到:为不同的 js 变量复制值时,结果是不同的。把字符串 a 的值复制给 b,改变b 的值不会影响 a 的值,而把数组 arr1 的值复制给 arr2 时,改变 arr2 的值,arr1的值也跟着改变了。

这是因为 js 存在两种不同数据类型的值:基本类型值 引用类型值
在访问这两种类型的变量时,其访问方式是不同的。在这里,先记一下结论:

  • 基本数据类型是 按值访问的
  • 引用数据类型是 按引用访问的
    ( 实际上这种说法并不严密,为便于理解,我们先这么记)

什么意思?
JavaScript 不允许直接访问内存中的位置,换句话说,不能直接操作对象的内存空间。
因此,在操作对象时,我们实际上是在操作对象的引用,而不是实际的对象

从一个变量向另一个变量复制值时(不管是复制基本类型还是引用类型),都会先为这个新变量分配一个空间,然后把该值复制到新创建的这个空间里。
不同的是,在复制引用类型的值时,实际上复制过去的是一个指针,示例图如下:

在 js 中,除了 7 种基本类型外,其他的都是引用类型,比如Object,Array,Function,所以不难理解:

let obj1 = {name:'hx',age:18};
let obj2 = obj1;
obj2.age = 0;
console.log(obj1);
// {name:'hx',age:0}

正文完
 0