在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