js 陣列深度拷貝詳解
js 陣列深度拷貝詳解
1.我們已經知道的深拷貝和淺拷貝的區別,在於,深拷貝是拷貝值的同時擁有一個新的儲存地址,而淺拷貝只是拷貝了值,而儲存地址不變;這樣會導致的問題是修改拷貝的值,會同時修改原陣列;
但是你所知道深拷貝真的就是深拷貝嗎?
淺拷貝示例:
var arr = [1,2,3,4]
let newArr = arr //淺拷貝
newArr.splice(0,1)
console.log(arr,'原陣列'); //[2, 3, 4] "原陣列"
console.log(newArr,'淺拷貝陣列') //[2, 3, 4] "拷貝陣列"
深拷貝示例:
第一種 利用陣列api slice 和 map 返回一新陣列的特性
var arr = [1,2,3,4]
let newArr = arr.slice(0) //深拷貝
newArr.splice(0,1)
console.log(arr,'原陣列'); //[1, 2, 3, 4] "原陣列"
console.log(newArr,'深拷貝陣列') //[2, 3, 4] "拷貝陣列"
//map
let newArr2 = arr.map(item=>{
return item
})
newArr2.splice(0,1)
console.log(arr,'原陣列'); //[1, 2, 3, 4] "原陣列"
console.log(newArr2,'深拷貝陣列') //[2, 3, 4] "拷貝陣列"
第二種 建立新陣列儲存
var arr = [1,2,3,4]
let newArr3 = []
for(var i=0 ;i<arr.length;i++){
newArr3.push(arr[i])
}
newArr3.splice(0,1)
console.log(arr,'原陣列'); //[1, 2, 3, 4] "原陣列"
console.log(newArr3,'拷貝陣列') //[ 2, 3, 4] "拷貝陣列"
第三種 利用 JSON.stringify() ,JSON.parse() 之間的轉換
var arr = [1,2,3,4]
let newArr4 = JSON.parse(JSON.stringify(arr))
newArr4.splice(0,1)
console.log(arr,'原陣列'); //[1, 2, 3, 4] "原陣列"
console.log(newArr4,'拷貝陣列') //[ 2, 3, 4] "拷貝陣列"
但是這種方法有一定缺陷,不能轉換function,還有undefined
var arr2 = [1,2,3,function(){console.log(11)},undefined,null]
let newArr4 = JSON.parse(JSON.stringify(arr2))
newArr4.splice(0,1)
console.log(arr2,'原陣列'); //[1, 2, 3, ƒ] "原陣列"
console.log(newArr4,'拷貝陣列') // [2, 3, null,null,null] "拷貝陣列"
上述方法是能實現深拷貝,但我們需要了解當陣列中有層級,是否能深拷貝呢?
要知道,比方一個陣列 arr =[{a:1,b:2}],這個陣列arr儲存在一個地址中,而其中的arr[0].a儲存的地址卻是裡另一個地址,相當於引用傳遞,這時簡單的深拷貝將不能拷貝這個深層級的拷貝
多層級拷貝錯誤示例:
var arr1 = [{a:1,b:1}]
let newArr1 = arr1.slice(0)
newArr1.forEach(item=>{
delete item.a
})
console.log(arr1,'原陣列'); //[{b:1}] "原陣列"
console.log(newArr1,'拷貝陣列') //[{b:1}] "拷貝陣列"
//第二種
var arr2 = [[1,2,3],[2,3,4]]
let newArr2 = []
for(var i=0 ;i<arr2.length;i++){
newArr2.push(arr2[i])
}
newArr2.forEach(item=>{
item.splice(0,1)
})
console.log(arr2,'原陣列'); //[[2,3],[3,4]] "原陣列"
console.log(newArr2,'拷貝陣列') //[[2,3],[3,4]] "拷貝陣列"
以上是無法實現多層級拷貝,但是JSON.stringify() ,JSON.parse() 卻可以
var arr1 = [{a:1,b:1}]
let newArr4 = JSON.parse(JSON.stringify(arr1))
newArr4.forEach(item=>{
delete item.a
})
console.log(arr1,'原陣列'); //[{a:1,b:1}] "原陣列"
console.log(newArr4,'拷貝陣列') //[{b:1}] "拷貝陣列"
換一個思路,既然每一層的地址不同,我們何不遍歷每一層的拷貝呢
var arr1 = [{a:1,b:1}]
function clone(obj){
if (obj instanceof Array) {
var copy = [];
for (var i = 0, len = obj.length; i < len; ++i) {
copy[i] = clone(obj[i]);
}
return copy;
}
}
let newArr5 = clone(arr1)
newArr5.forEach(item=>{
delete item.a
})
console.log(arr1,'原陣列'); //[{a:1,b:1}] "原陣列"
console.log(newArr5,'拷貝陣列') //[{b:1}] "拷貝陣列"
當然不同的物件有不同的clone,以下是筆者封裝的方法適用於多種物件
function clone(obj) {
// 判斷是否為空未定義
if (null == obj || "object" != typeof obj) return obj;
// Date
if (obj instanceof Date) {
var copy = new Date();
copy.setTime(obj.getTime());
return copy;
}
// Array
if (obj instanceof Array) {
var copy = [];
for (var i = 0, len = obj.length; i < len; ++i) {
copy[i] = clone(obj[i]);
}
return copy;
}
// Object
if (obj instanceof Object) {
var copy = {};
for (var attr in obj) {
if (obj.hasOwnProperty(attr)) copy[attr] = clone(obj[attr]);
}
return copy;
}
throw new Error("無法複製物件!不支援其型別。");
}
相關文章
- js 陣列的淺拷貝和深拷貝JS陣列
- 14 個拷貝陣列的 JS 技巧陣列JS
- js陣列物件複製拷貝不改變原來的值,深拷貝JS陣列物件
- Js深度拷貝解決雙向繫結問題JS
- JavaScript 深度拷貝和淺拷貝JavaScript
- 詳解js中的物件的深淺拷貝JS物件
- js陣列方法詳解JS陣列
- 如何深淺拷貝陣列(總結)陣列
- 深拷貝和淺拷貝的簡要詳解
- 深度解析深拷貝和淺拷貝
- js 淺拷貝和深拷貝JS
- JS深拷貝與淺拷貝JS
- js 深拷貝和淺拷貝JS
- Python 擴充之詳解深拷貝和淺拷貝Python
- js的深拷貝和淺拷貝JS
- js之淺拷貝和深拷貝JS
- 深入理解 JavaScript 物件和陣列拷貝JavaScript物件陣列
- 你不知道的簡單陣列拷貝方法全解陣列
- 淺探js深拷貝和淺拷貝JS
- js實現深拷貝和淺拷貝JS
- js陣列方法詳解(最新最全)JS陣列
- 理解JS中的淺拷貝與深拷貝JS
- js 深拷貝方法JS
- js深拷貝方法JS
- 【JS】深拷貝與淺拷貝,實現深拷貝的幾種方法JS
- vue的深度拷貝物件Vue物件
- jquery之物件拷貝深拷貝淺拷貝案例講解jQuery物件
- [JS系列二]談談深拷貝和淺拷貝,如何實現深拷貝JS
- 圖解 Python 淺拷貝與深拷貝圖解Python
- js資料型別賦值,淺拷貝,深拷貝JS資料型別賦值
- 在js中如何區分深拷貝與淺拷貝?JS
- JavaScript中十個一步拷貝陣列的方法JavaScript陣列
- JavaScript中十種一步拷貝陣列的方法JavaScript陣列
- JS中的深拷貝JS
- js實現深拷貝JS
- JS深拷貝總結JS
- JS 陣列(Arrey)屬性以及方法詳解JS陣列
- 瞭解一下js物件深拷貝與淺拷貝(前端開發面試)JS物件前端面試