js 深浅拷贝

60 阅读2分钟

开启掘金成长之旅!这是我参与「掘金日新计划 · 12 月更文挑战」的第37天,点击查看活动详情

问题分析

查看下面的代码,执行一下:

// 例子1
var name = '张三';
var userName= name;
name = '李四';

console.log(name, userName);

// 例子2
var ary1 = [1, 1, 2];
var ary2 = ary1;

ary1[1] = 3
console.log(ary1, ary2);

// 输出结果:
李四 张三
[ 1, 3, 2 ] [ 1, 3, 2 ]

执行以上代码,得到结果中你糊发现对 name 赋值后修改 name 值后互不影响,但是数组修改后,两个数组的值还是保持一致的。这和对象的存储有关系。在JS 中基础数据类型 string 、number、boolean、null、undefined 赋值是对值的传递。对象是存储在内存中,赋值时是传递的对象的地址,这样如果修改对象属性的值就导致原对象的值也发生改变。

浅拷贝

创建一个新对象,这个对象有着原始对象属性值的一份精确拷贝。如果属性是基本类型,拷贝的就是基本类型的值,如果属性是引用类型,拷贝的就是内存地址 ,所以如果其中一个对象改变了这个地址,就会影响到另一个对象。

深拷贝

将一个对象从内存中完整的拷贝一份出来,从堆内存中开辟一个新的区域存放新对象,且修改新对象不会影响原对象。

常见的拷贝有:

  • 像基础的赋值 “=” ,赋值的就是对象的引用。
  • 使用 Object.assign 对对象复制,但复制的是对象的的引用而不是对象的值本身。
  • _.cloneDeep()
  • JQuery 中提供 extend 方法
  • 使用 JSON.stringify() 方法但是其对 undefined、symbol 和函数 会被忽略,需要谨慎使用。

所以,对于基础数据类型没有深复制和浅复制,而引用类型就会有深复制和浅复制。浅复制和深复制都是对对象的值和引用地址的复制,但是深复制不会对原对象有影响。所以我的理解深复制应该是产生新的引用地址。