《JavaScript总结》深拷贝和浅拷贝

在javascript中,数据主要分基本类型和引用类型两种。javascript

基本类型的赋值比较简单,可是引用类型的赋值,会存在一些问题,那咱们用代码来分析一下。java

 

1、浅拷贝数组

 

var one = "测试1"; var two = one; two = "测试2"; console.log(one);

 

上面代码中,声明了一个变量one ,值为:“测试1” ,而后将变量one 赋值给了变量two ,函数

以后咱们把变量two的值修改为:“测试2” 了,这时咱们从控制台打印变量one ,输出的结果是:“测试1”。测试

也就是说修改变量two的值并不会对变量one形成影响。spa

 

那咱们再来看下面这个例子:code

 

var arr = ['白色','蓝色','紫色']; var temp = arr; temp[1]="天蓝色"; console.log(arr);

 

上面这段代码,控制台打印输出了  ‘白色’,'天蓝色','紫色'  ,这是怎么回事呢?咱们明明修改的是temp,怎么arr也被修改了?对象

这其实很简单,由于在javascript中,数组属于引用类型数据。在上面的例子中,当把arr赋值给temp时,其实只是把访问地址赋值给了temp blog

 

咱们来分析一下代码递归

 

var arr = ['白色','蓝色','紫色'];

在javascript中,数组的大小是不肯定的,这时js会在堆内存中创建一块内存,用来存一个数组,而这个数组的值目前为:['白色','蓝色','紫色'] ,而后会生成一个地址,而且赋值给了arr ,

因此说arr存的是 ['白色','蓝色','紫色'] 在堆内存中的访问地址。

 

var temp = arr;

由于arr存的是一个地址,这时将arr赋值给了temp ,因此temp也拥有访问['白色','蓝色','紫色']的地址了。

 

temp[1]="天蓝色";

那么这时咱们将temp[1]的值修改为了“天蓝色”,这一操做,首先temp经过地址访问堆内存对应的数据,而且修改了数据。

由于arr和temp存的只是访问同一个源的地址,源被temp改变了,arr再次访问时,访问的也就是改变过的源了。

 

但有时候,咱们修改一个数据的时候,并不想影响另外一个数据,使用深拷贝就能够解决这个问题。

 

2、深拷贝

 

数组中的深拷贝

数组实现深拷贝的方法:使用slice()或cancat()方法,或者是使用循环将当前数组的值,一个一个添加到新的数组中便可。

var arr = [1,3,4]; var temp = arr.slice(0); temp[0]=6; console.log(arr);//输出 1,3,4 不会被temp影响
var arr = [1,3,4]; var temp =arr.concat([]); temp[0]=6; console.log(arr);//输出1,3,4 不会被temp影响

其实上面两种都属于简单的深拷贝,若是是二维数组、三维数组呢?咱们看一个例子

var ac = [1,[2,3],4]; var ad = ac.slice(0); ad[1][0]=6; ad[0]=5; console.log(ac);

控制台输出结果以下:

使用了简单的深拷贝(slice方法)以后,能够发现ac的第一个值确实不受ad的影响,可是ac的第二个值却随着ad的改变而改变了。更深层的拷贝怎么办呢?其实能够利用递归函数来解决这个问题

        var duowei = [1,[2,3],4]; function dispose(data){ var out = []; for(var i =0;i<data.length;i++){ if(data[i] instanceof Array){ out[i]=dispose(data[i]); }else{ out[i]=data[i]; } } return out; } var result = dispose(duowei); result[1][0]=9; console.log(duowei); 

 

对象中的深拷贝

在对象中简单的深拷贝可使用Object.assign来实现

let a = { age: 1 } let b = Object.assign({}, a) a.age = 2 console.log(b.age) // 1

 

复杂的深拷贝可使用JSON.parse(JSON.stringify(object))来解决,不过这个方法有一些局限性。

  • 会忽略 undefined
  • 会忽略 symbol
  • 不能序列化函数
  • 不能解决循环引用的对象
let a = { age: 1, jobs: { first: 'FE' } } let b = JSON.parse(JSON.stringify(a)) a.jobs.first = 'native' console.log(b.jobs.first) // FE

 

其实方法有不少,须要本身去挖掘。

这里在分享一个数组和对象实现简单深拷贝通用的方法:经过展开运算符(…)来实现。

let a = { age: 1 } let b = {...a} a.age = 2 console.log(b.age) // 1
相关文章
相关标签/搜索