# 淺拷貝與深拷貝
## 為什麼需要這個?是為解決什麼問題?
> 解決物件/陣列的拷貝問題
* 各自的使用場景
* 淺拷貝→當今天資料只有一層時,使用淺拷貝可以更輕量、不消耗太多資源的進行拷貝,它只複製最外層的結構,而不涉及內部對象的複製,這樣可以節省時間和資源
* 深拷貝→我們需要一個完全獨立的副本而不想修改到原始資料時,可以使用深拷貝
狀況一、物件沒有被實際拷貝
```javascript
let a = [1,2]
let b = a // 沒有建立新物件,參考到同一個物件實體
b[0]=3
console.log(a)//[3,2]
```
狀況二、物件拷貝→兩物件之間無關連性了
```javascript
let a = [1,2]
let b = [...a] // 建立新物件,並複製原物件的資料
b[0]=3
console.log(a)//[1,2]
```
## 淺拷貝 Shallow copy
> 僅「真正」拷貝物件的第一層資料
* 僅第一層會是不同的參考
* 常見的拷貝工具都是淺拷貝
```javascript
let a = {
x:1,
y:2,
data:[3,4,5]
}
let b = {...a}
let c = Object.assign([],a)
b.data[0] = 30
console.log(a.data[0]) // 30 →原本的 a 被改變了
```
## 深拷貝 Deep copy
> 完全拷貝物件底下「所有」層次的資料
> 建立兩個完全獨立的物件實體
### 方法一:JSON.parse(JSON.stringify(...))
* 使用 JS 內建方法 JSON.stringify() 將物件字串化(序列化 Serialize)
* 使用JSON.parse() 根據字串化的資料重新建立物件結構,完成深拷貝
```javascript
let a = {
x:1,
y:2,
data:[3,4,5]
}
let b =JSON.parse(JSON.stringify(a))
b.data[0] = 30
console.log(a.data[0]) // 3 →原本的 a 沒有被改變了
```
#### ==JSON方法的限制==
* 無法拷貝不能字串化的資料
* 無法拷貝函式或是 symbol 等資料
### 方法二:structuredClone
使用 JS 內建方法 structuredClone
```javascript
let a = {
x:1,
y:2,
data:[3,4,5]
}
let b = structuredClone(a)
b.x = 200
console.log("a",a.x)//1
console.log("b",b.x)//200
```
### 方法三:遞迴
建立 deepCopy function 思考:
1. 利用 typeof 判斷傳進來的物件是否為 object
2. 若不是,代表沒有需要拆解的第二層資料→return
3. 若是,繼續呼叫 deepCopy
```javascript
function deepCopy(obj){
// 1.檢查是否為物件,如果不是,直接返回
if(typeof obj !== "object"&& obj !== null){
return
}
// 2.創建一個新的空物件或陣列,根據原始物件的類型
const newObj = Array.isArray(obj):[]?{}
// 3.遞迴複製原始物件的每個屬性或元素
for(let key in obj){
// 進行拷貝(單維的 shallow copy 會建立兩個實體)
// js object bracket notation
// const c = {x:10,y:20}
// console.log(c["y"])//20
newObj[key] = deepCopy(obj[key])
}
return newObj
}
let a = {
x:1,
y:2,
data:[3,4,5]
}
let b =deepCopy(a);
b.data[0] = 30
console.log(a.data[0] )// 3
```
完成深拷貝!