一早和小夥伴被一個奇妙的問題給卡住,在 Parsing 資料我們經常使用 For 迴圈,每一次創建一個資料物件,並將其加入 Array,最後產出要的東西,#世界真美好。
可惜世界經常不是這樣運作。
我們知道都知道 Object 和 Array 是 Pass By Reference,所以如果沒有在迴圈中宣告新的物件,最後陣列裡的物件都會被改為最後一次迴圈的資料,像這樣:
const data = { 1: {id: 1, name: 'a'}, 2: {id: 2, name: 'b'}, }; const resultArr = []; const tempObj = {}; Object.keys(data).forEach(key => { tempObj.id = data[key].id; tempObj.name = data[key].name; resultArr.push(tempObj); }) console.log(resultArr); /* output: [ {id: 2, name: "b"}, {id: 2, name: "b"} ]; */
當然啦,知道物件是 Pass By Reference,只要在 For 迴圈裡加入 let tempObj = {}
,讓每次執行時都創建一個物件,可以輕而易舉解決這個問題。
但這時突然一個異想天開,如果把 tempObj 在 For 迴圈中重新賦值會怎麼樣呢~
let data = { 1: {id: 1, name: 'a'}, 2: {id: 2, name: 'b'}, }; const resultArr = []; var tempObj = {}; Object.keys(data).forEach(key => { tempObj = {}; tempObj.id = data[key].id; tempObj.name = data[key].name; resultArr.push(tempObj); }) console.log(resultArr) /* output: [ {id: 1, name: "a"}, {id: 2, name: "b"} ]; */
有些人把這樣的形式稱為 Pass By Sharing,一開始物件是指向同一個位置沒錯,但當把物件重新賦值時,就會指向新的物件,外面的物件不會受到影響。
更簡單的範例可以參考以下。
See the Pen Pass By Sharing by Winter (@yichinweng) on CodePen.
延伸閱讀:
1. 重新認識 JavaScript: Day 05 JavaScript 是「傳值」或「傳址」?
2. 深入探討 JavaScript 中的參數傳遞:call by value 還是 reference?