# JS:  Destructuring 解構

這幾天在複習後端和製作RESTful API，想用解構的方式把 `req.body` 拆成變數，再用mongoose傳入mongoDB更新資料。

例如我預期可以接收到API參數有 id, name, age, major, merit, other，所以寫了一個解構語法拆解 req.body 物件 `const {id, name, age, major, merit, other} = req.body;`。

假設使用者只在 name 和 age 輸入參數值，結果發現**在沒有給定屬性預設值的情況下**，即使解構時特別指定變數名稱，沒對應到物件屬性就不會被解構出來。

換句話說JS的解構語法，只會解構出有屬性存在的變數，因此上述解構出來的變數只存在 `name` 和 `age`。
<br/>

## 會造成什麼樣的問題？

我在連結資料庫更新資料的方式是，傳入 `id` 去查找。

_如果使用者沒輸入 `id`，在用 mongoose 的 findOneAndUpdate() 因為不會輸入查詢值，就會直接跳出查詢，而且我也不會收到錯誤_😅

為了避免沒有輸入 `id` ，我這邊是給定 `id=null` (下圖)，因為 mongoose 的 Schema 有設定 `id:{required: true}`，在更新資料那邊會偵測 id 是否為 null，若沒有就會給錯誤訊息，所以我就可以用 `res.send(error)` 偷懶地把 mongoose 錯誤訊息傳回去給使用API的人。
<img src="https://i.imgur.com/Eom5qAF.png" style="width: 700px"/>
<br/>

## 目前的解決辦法？
目前想到兩種解決辦法。

第一個是：**先把每個解構的變數都給定預設值**，強迫每個變數在解構沒有取得變數值的情況下，確保有這個變數且值為 `null`，例如：
```
const {
    id = null
    , name = null
    , age = null
    , major = null
    , merit = null
    , other = null
} = req.body;
```
並且在查找前就要判斷 `id === null` ，不過這邊就是不想加入自訂錯誤訊息的偷懶作法，之後有修正更正確的版本再回來更新圖片。
<br/>

(_2022.05.26 Updated_)
第二種作法是先確認 `req.body` 是否擁有所有需要更新的屬性資料，我這邊的作法是用 Array 的 `every` method 去確認 req.body 是否有同名的key。確認無誤才把  `req.body` 拿去更新資料庫。
```
const properties = ["id", "name", "age", "major", "merit", "other"];
if(properties.every(p => p in req.body){
    res.status(400)
        .send({
            "Error": "Please update all the property value of this data"
        })
} else{
    // destructuring req.body and put the data into database
}
```

*後記：*
速看了一下[MDN](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Destructuring_assignment)好像也沒特別說這件事, 還是這是常識? 總之先記錄一下這個發現。

---
References
- [Destructuring assignment](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Destructuring_assignment)
