我們在js程式中需要進行頻繁的變數賦值運算,對於字串、布林值等可直接使用賦值運算子 「=」 即可,但是對於陣列、物件、物件陣列的拷貝,我們需要理解更多的內容。
首先,我們需要了解js的淺拷貝與深拷貝的區別。
我們先給出乙個陣列:
var arr = ["a","b"];
現在怎麼建立乙份arr陣列的拷貝呢?直接執行賦值運算嗎?我們來看看輸出結果
var arrcopy =arr;arrcopy[1] = "c";
arr
//=> ["a","c"]
可以發現對拷貝陣列 arrcopy 進行操作時原陣列也相應地被改變了,這就是js的淺拷貝模式。所以我們可以指出對陣列、物件、物件陣列進行簡單賦值運算只是建立了乙份原內容的引用,指向的仍然是同一塊記憶體區域,修改時會對應修改原內容,而有時候我們並不需要這種模式,這就需要對內容進行深拷貝。
1 陣列的深拷貝
對於陣列的深拷貝常規的有三種方法:
方法一:遍歷複製
1var arr = ["a", "b"], arrcopy =;
2for (var item in arr) arrcopy[item] =arr[item];
3 arrcopy[1] = "c";
4 arr //
=> ["a", "b"]
5 arrcopy //
=> ["a", "c"]
考慮偽多維陣列可以寫成函式形式:
functionarrdeepcopy(source)
這種方法簡單粗暴,但是利用js本身的函式我們可以更加便捷地實現這個操作。
方法二:slice()
呼叫格式為:
arrayobject.slice(start,end)方法返回乙個新的陣列,包含從 start 到 end (不包括該元素)的 arrayobject 中的元素。該方法並不會修改陣列,而是返回乙個子陣列。
在這裡我們的思路是直接從陣列開頭截到尾:
arrcopy = arr.slice(0);arrcopy[1] = "c";
arr
//=> ["a", "b"]
arrcopy //
=> ["a", "c"]
可以看出成功建立了乙份原陣列的拷貝。
方法三:concat()
呼叫格式為:
arrayobject.concat(arrayx,arrayx,......,arrayx)該方法不會改變現有的陣列,而僅僅會返回被連線陣列的乙個副本。
使用這種方法的思路是我們用原陣列去拼接乙個空內容,放回的便是這個陣列的拷貝:
arrcopy =arr.concat();arrcopy[1] = "c";
arr
//=> ["a", "b"]
arrcopy //
=> ["a", "c"]
2、物件的深拷貝
對於陣列的深拷貝我們有了概念,那麼一般物件呢?
我們給出乙個物件:
var obj = ;
同樣做測試:
var objcopy =obj;objcopy.b = 3;
obj
//=>
objcopy //
=>
同樣,簡單的賦值運算只是建立了乙份淺拷貝。
而對於物件的深拷貝,沒有內建方法可以使用,我們可以自己命名乙個函式進行這一操作:
var objdeepcopy = function(source);
for (var item in source) sourcecopy[item] =source[item];
return
sourcecopy;
}
但是對於複雜結構的物件我們發現這個函式並不適用,例如:
var obj = , "b": 2 };
所以需要進行一點修改:
var objdeepcopy = function(source);
for (var item in source) sourcecopy[item] = typeof source[item] === 'object' ?objdeepcopy(source[item]) : source[item];
return
sourcecopy;
}var objcopy =objdeepcopy(obj);
objcopy.a.a1[1] = "a13";
obj
//=> , "b": 2 }
objcopy //
=> , "b": 2 }
3、物件陣列的深拷貝
如果再考慮更奇葩更複雜的情況,例如我們定義:
var obj = [, "b": 2 }, ["c", ]];
這是乙個由物件、陣列雜合成的奇葩陣列,雖然我們平時寫程式基本不可能這麼折騰自己,但是可以作為一種特殊情況來考慮,這樣我們就可以結合之前說的方法去拓展拷貝函式:
var objdeepcopy = function(source) ;
for (var item in
source)
return
sourcecopy;
}var objcopy =objdeepcopy(obj);
objcopy[0].a.a1[1] = "a13";
objcopy[1][1].e = "6";
obj
//=> [, "b": 2 }, ["c", ]]
objcopy //
=> [, "b": 2 }, ["c", ]]
這樣它就可以作為乙個通用函式替我們進行深拷貝操作了。
JS中深拷貝陣列 物件 物件陣列方法
我們在js程式中需要進行頻繁的變數賦值運算,對於字串 布林值等可直接使用賦值運算子 即可,但是對於陣列 物件 物件陣列的拷貝,我們需要理解更多的內容。首先,我們需要了解js的淺拷貝與深拷貝的區別。我們先給出乙個陣列 var arr a b 現在怎麼建立乙份arr陣列的拷貝呢?直接執行賦值運算嗎?我們...
js中深拷貝陣列,物件,物件陣列方法
首先看看這邊講的 在js中,對於字串,布林值可直接使用賦值運算子就可以實現深拷貝,但對於引用型別,陣列,物件,物件陣列的拷貝呢,實際只是進行了淺拷貝 下面是乙個陣列 var arr a b 現在怎麼進行arr陣列的拷貝呢,直接賦值來的結果 var arrcopy arr arrcopy 1 c ar...
JS深拷貝陣列和物件
有時候在些js 時不小心直接給陣列和物件直接賦值,可能不會直接產生什麼 但若是遇到了奇怪的問題了,這很有可能就是在拷貝陣列或者物件時時進行淺拷貝,接受者在不知不覺地改變了某些元素的值,從而導致原始值就莫名其妙地被同步修改了 面對這種情況,最好對陣列或者物件進行深拷貝,為了不影響某些元素的丟失 比如某...