剛開始接觸到 JS 的時候,讀了相關書籍時,看到有關淺拷貝跟深拷貝的問題。
當下不是有很強烈的感覺,畢竟沒碰過。
直到我開始寫 Vue 時,要處理資料這一塊,使用了 prop 傳值到子 component 。
意外發現不需要 emit 回父 component ,這時才慶幸那時候知道 JS 有 call by reference 這個問題。

既然如此,如果想要將資料拷貝,有幾種方式。

JSON

首先是使用 JSON 拷貝方式:

1
let newObj = JSON.parse(JSON.stringify(oldObj))

使用 JSON 去拷貝,能良好的將你拿到的資料拷貝一份新的,無論他有幾層都可以。
缺點是因為 JSON 不能拷貝 function ,所以遇到 function 只能另闢蹊徑。

淺拷貝

如果你的資料只有一層,使用淺拷貝即可

array

1
2
let a = [1, 2, { x: 1 }]
let b = Array.from(a) //淺拷貝

object

1
2
let c = { x: 1, y: { w: 1, v: 2 } }
let d = Object.assign({}, c) //淺拷貝

以上這兩種方式只能拷貝第一層,
第二層之後的還是會受 call by reference 影響,
a[2]b[2]c.yd.y
其指向為同一位址。

深拷貝

如果有兩層的資料,又有 function 需要被拷貝,就要使用深拷貝了

1
2
3
4
5
6
7
8
9
10
11
12
function deepCopy(inputData) {
if (typeof inputData !== 'object') return inputData
let newCopy = Array.isArray(inputData) ? [] : {}
for (let prop in inputData) {
if (typeof inputData[prop] === 'object') {
newCopy[prop] = deepCopy(inputData[prop])
} else {
newCopy[prop] = inputData[prop]
}
}
return newCopy
}

這個 function 用到了遞迴,當遇到非 object 或 array 就會直接回傳輸入值,
如果是 object 或 array,就會創立一個新的 {} 或 [] 並再檢查一次