目錄
一、理解拷貝
二、基本資料型別拷貝
三、淺拷貝(shallow clone)
物件淺拷貝
(1)依次賦值
(2)for..in 遍歷
(3)Object.assign(目標物件,要拷貝的物件)
(4)展開運算子
缺陷:只能拷貝外層不能拷貝內層
陣列淺拷貝
(1)依次賦值
(2)展開運算子
(3)slice
(4)map
四、深拷貝
物件陣列深拷貝
(1)遞回
(2)JSON.parse(JSON.stringify())
一、理解拷貝
拷貝就像我們平常cv一些檔案、代碼 復制了一份新的就叫拷貝, 換成js代碼就變成了基本資料型別和參考資料型別的拷貝,
在JavaScript中我們定義的簡單資料型別會存到堆疊(stack)記憶體中,包括參考型別的指標,而這個指標指向的地方是在堆(heap)記憶體中,也通常理解為,簡單資料型別存在堆疊中,參考資料型別存在堆中

二、基本資料型別拷貝
基本資料型別沒什么好說的,通過一個變數賦值給一個變數就已經拷貝完成了
let a = 1
let b = a

把a賦值給b之后 再去操作a并不會影響b 你可以理解為 a 和b 是兩個不同的區域,但都是存在堆疊記憶體里,
let a = 1
let b = a
a=5
console.log(b); //1
console.log(a); //5
三、淺拷貝(shallow clone)
淺拷貝只能拷貝復雜資料型別的指標,并不能改變復雜資料型別的地址,只能拷貝外層,并不能徹底拷貝,例如陣列中還有陣列(物件),(準確來說是外層參考資料型別)
物件淺拷貝
(1)依次賦值
優點:數量較少的時候使用方便、簡單,缺點:遇到物件或陣列鍵比較多時,操作不方便
let obj = {
a: {name: 'abc'},
b: 2
}
let newObj = {}
newObj.a=obj.a
newObj.b=obj.b
(2)for..in 遍歷
let obj = {
a: {name: 'abc'},
b: 2
}
let newObj = {}
for (const key in obj) {
newObj[key]=obj[key]
}
(3)Object.assign(目標物件,要拷貝的物件)
let obj = {
a:{name:'奧特曼'},
b:2
}
let newObj= {}
Object.assign(newObj,obj)
(4)展開運算子
let obj = {
a: {name: 'abc'},
b: 2
}
let newObj = {}
newObj = {...obj}
缺陷:只能拷貝外層不能拷貝內層
淺拷貝只能拷貝最外層的參考地址,并不能拷貝內層的參考地址
修改最內層的資料 另一個也會改變,因為指標指向的的都是同一個記憶體地址
newObj.a.name='bcd'
console.log(obj); //a: {name: "bcd"}, b: 2
console.log(newObj); //a: {name: "bcd"}, b: 2
陣列淺拷貝
(1)依次賦值
let arr = [1,{name:'abc'}]
let newArr = []
newArr[0]=arr[0]
newArr[1]=arr[1]
(2)展開運算子
let arr = [1,{name:'abc'}]
let newArr = [...arr]
(3)slice
let arr = [1,{name:'abc'}]
let newArr = arr.slice(0)
(4)map
let arr = [1,{name:'abc'}]
let newArr = arr.map(it=>it)
同樣修改陣列中記憶體的資料 另一個陣列的記憶體資料也會改變
arr[1].name='bcd'
console.log(arr);// 1, {name: "bcd"}
console.log(newArr);// 1, {name: "bcd"}
四、深拷貝
深拷貝:不光外層的參考地址該變了 內層的參考資料型別也發生改變
物件陣列深拷貝
(1)遞回
obj = {
a: {name: 'abc'},
b: 2
}
function fn(obj) {
let newObj = {}
// 如果不是物件直接回傳
if(typeof obj !=='object'){
return '不是一個物件'
}else {
// 是物件就對每一項進行遍歷
for (const key in obj) {
// 判斷內部是否為物件 如果不是物件就進行遞回
if(typeof obj[key] ==='object'){
newObj[key]=fn(obj[key])
}else{
newObj[key]=obj[key]
}
}
}
return newObj
}
優化
obj = {
a: { name: 'abc' },
b: 2
}
function fn(obj) {
let newObj = {}
if(typeof obj !=='object') return '不是一個物件'
for (const key in obj) {
typeof obj[key] ==='object'? newObj[key]=fn(obj[key]): newObj[key]=obj[key]
}
return newObj
}
let newObj = fn(obj)
這時候在修改物件里面的參考型別時 就不會影響另一個物件
newObj.a.name='bcd'
console.log(obj);
console.log(newObj);
(2)JSON.parse(JSON.stringify())
let newObj = JSON.parse(JSON.stringify(obj))
這個深拷貝我們經常會在網上看到,但也不是沒有缺陷
obj = {
a:NaN,
b: undefined,
c:new Date(),
d:new RegExp(/\d/),
d:new Error(),
e:Infinity
}
console.log(obj);
let newObj = JSON.parse(JSON.stringify(obj))
console.log(newObj);
對比圖

JSON.parse(JSON.stringify())拷貝后的缺陷:
- NaN ===》null
- undefined ===》 空
- 時間戳 ===》字串時間
- 錯誤資訊 ===》 空物件
- Infinity ===》null

轉載請註明出處,本文鏈接:https://www.uj5u.com/qianduan/292979.html
標籤:其他
上一篇:手把手教你制作簡易的計算器
