---
# System prepended metadata

title: 請描述此段程式碼，哪裡用到物件 push 與取值概念、寫第四關主線任務破關流程

---

請描述此段程式碼，哪裡用到物件 push 與取值概念、寫第四關主線任務破關流程
===

````javascript=
// 小步測試，反覆驗證
let bmiHistoryData = [];
const bmiStatesData = {
  "overThin": {
    "state": "過輕",
    "color": "藍色"
  },
  "normal": {
    "state": "正常",
    "color": "紅色"
  },
  "overWeight": {
    "state": "過重",
    "color": "澄色"
  },
  "mildFat": {
    "state": "輕度肥胖",
    "color": "黃色"
  },
  "moderateFat": {
    "state": "中度肥胖",
    "color": "黑色"
  },
  "severeFat": {
    "state": "重度肥胖",
    "color": "綠色"
  },
}
function bmiStatesText(state) {
  console.log(`您的體重${bmiStatesData[state].state}，健康指數為${bmiStatesData[state].color}`)
}
function addData(bmi,state){
  let obj = {};
  obj.bmi = bmi;
  obj.state = state;
  bmiHistoryData.push(obj);
}
function printBmi(height, weight) {
  // let height = 178;
  // let weight = 130;
  let bmi = (weight / ((height / 100) * (height / 100))).toFixed(2);
  // console.log(bmi);
  if (bmi < 18.5) {
    addData(bmi, "overThin")
    //overThin
    bmiStatesText("overThin");
  } else if (18.5 <= bmi && bmi < 24) {
    //normal
    bmiStatesText("normal");
    addData(bmi, "normal");
  } else if (24 <= bmi && bmi < 27) {
    //overWeight
    bmiStatesText("overWeight");
    addData(bmi, "overWeight");
  } else if (27 <= bmi && bmi < 30) {
    //mildFat
    bmiStatesText("mildFat");
    addData(bmi, "mildFat");
  } else if (30 <= bmi && bmi < 35) {
    //moderateFat
    bmiStatesText("moderateFat");
    addData(bmi, "moderateFat")
  } else if (bmi >= 35) {
    //severeFat
    bmiStatesText("severeFat");
    addData(bmi, "severeFat")
  } else {
    console.log("您的數值輸入錯誤，請重新輸入")
  }
}
function showHistoryData(){
  const totalNum = bmiHistoryData.length;
  const lastNum = totalNum - 1;
  const lastState = bmiHistoryData[lastNum].state
  console.log(`您總共計算 ${totalNum} 次 BMI 紀錄，最後一次 BMI 指數為 ${bmiHistoryData[lastNum].bmi}，體重${bmiStatesData[lastState].state}！健康指數為${bmiStatesData[lastState].color}！`);
}
// 輸入數據，顯示對應物件內容
printBmi(178, 20);
printBmi(178, 70);
printBmi(178, 85);
showHistoryData();

````

----

## 問題 1：哪裡用到物件 push 概念
程式碼第 36 行，將 if 判斷式的 bmi 值和體重的 state，push 到 bmiHistoryData 陣列。

----

## 問題 2：哪裡用到物件取值概念
(1) 程式碼第 30 行，將 bmiStatesData 物件中的體重狀態(state)、健康指標(color)抓出來，給 function bmiStatesText 使用。
(2) 程式碼第 74 行，從 bmiHistoryData 陣列內的最後一個物件，取出屬性 state 的值賦予在 lastState 上。
(3) 程式碼第 75 行，最後一次輸入的 bmi 指數是從 bmiHistoryData 陣列內最後一個物件的 bmi 屬性抓到 BMI 值。
(4) 程式碼第 75 行，最後一次輸入的健康指數，是先宣告一個變數 lastState，再從 bmiHistoryData 陣列中的最後一筆物件抓出屬性 state 的字串並賦予到 lastState 變數上，最後再把變數 lastState 代入到 bmiStatesData 這個物件中，以物件取值代入變數的方式，分別取到體重狀態(state)、健康指標(color)的值。

----

## 問題 3：寫第四關主線任務破關流程

### :dart: Step 1：先分析一共有幾個 function 與它們分別擔任的功能是什麼？
- 第一個 **function printBmi(height, weight)**：
(1) 輸入：身高、體重的數值。
(2) 輸出：BMI 值。

- 第二個 **function bmiStatesText(state)**：
(1) 輸入：將狀態("overThin", "normal"...)傳送到 bmiStatesData 物件中。
(2) 輸出：印出從 bmiStatesData 回傳的("過輕"、"正常"...)及健康指數("藍色"、"紅色"...)。

- 第三個 **function addData(bmi, state)**：
(1) 輸入：由 if 判斷式運算的結果會丟出一個 bmi 值，及手動輸入狀態("overThin", "normal"...)。
(2) 輸出：由 obj 這個物件，紀錄儲存 bmi 及 state 資料，再把這個物件 push 到 bmiHistoryData 陣列中。

- 第四個 **function showHistoryData()**：
(1) 輸入：呼叫函式 showHistoryData(); 之後，開始輸入從 bmiHistoryData 陣列取得 length 的值、最後一筆物件資料的 bmi，另外還有 bmiStatesData 內的狀態(state)及健康指數(color)。
(2) 輸出：印出分別從 bmiHistoryData 陣列及 bmiStatesData 物件取得的值。

- 小結：這邊會發現四個 function 的功能是逐步疊加出三個階段的顯示資料。

### :dart: Step 2：宣告 function printBmi
這個步驟主要把 BMI 公式設定好、並逐步測試 BMI 的if判斷式是可運作的。

### :dart: Step 3：宣告 function bmiStatesText(state)
在這個步驟主要是確認 bmiStatesData 內的資料是可以抓得到的(也就是最終顯示結果的一半：您的體重**過輕**，健康指數為**藍色**)。
方法是在 if判斷式內呼叫 bmiStatesText(state) 這個函式，從 bmiStatesData 取值代入 console.log 確認可以顯示。

### :dart: Step 4：宣告一個空陣列 bmiHistoryData 
陣列 bmiHistoryData 準備等一下儲存從 function printBmi 傳(push)過來的資料。


### :dart: Step 5：宣告 function addData(bmi, state)
首先，先進行逐步測試，在 function printBmi 其中一個 if 條件中，可以先開一個空的物件 obj，從判斷式把 bmi 值、state("overThin", "normal"...)這兩個值存進去。

確認物件 obj 有存到資料後，接著，再把這個物件 obj 試著 push 到陣列 bmiHistoryData 之中，並確認陣列 bmiHistoryData 有收到資料。

最後，把剛才宣告的 obj 移到 function addData(bmi, state)之中。

之後透過 if 判斷式來觸發呼叫函式 addData(bmi, state)，將每一筆組合完成的 obj 存到陣列 bmiHistoryData。

### :dart: Step 6：宣告 function showHistoryData()
這個函式的主要功能是，組合再輸出最終的BMI運算結果的資料：

:one: **輸出計算 BMI 的總次數**
:arrow_right: 透過 length 語法得知 bmiHistoryData 陣列中有幾筆資料，就代表計算了幾次。

:two: **輸出最後一次計算的 BMI 數值**
:arrow_right: 既然所有的計算結果都會透過 addData 函式推送到 bmiHistoryData 陣列中，故可從此陣列的最後一筆物件資料取出最後一次計算的 BMI 值。

:three: **輸出最後一次計算的 BMI 對應的體重狀態 (正常或過重...)**
:arrow_right: 這邊需要拆解成兩個部分來看：
1. 體重狀態(state)及健康指數(color)都是存在 bmiStatesData 這個物件中，因此要取用資料的時候也必定要經過 bmiStatesData。
2. 因為是要求「最後一次」BMI 的體重狀態，可知一定要透過走 bmiHistoryData 陣列這個路徑才能取得資料。
3. 方法是宣告一個 lastState 變數，從最後一次計算的 BMI 值所對應的 state 取值，再賦予值到 lastState 變數上。
4. 用 lastState 變數代入 bmiStatesData 物件取值。

:four: **輸出最後一次計算的 BMI 對應的健康指數 (顏色)**
:arrow_right: 步驟跟取體重狀態相同。

----

### :bookmark: 參考資料

[請描述此段程式碼，哪裡用到物件 push 與取值概念、寫第四關主線任務破關流程](https://hackmd.io/7fjeQpF1TIyIeLQ_Sz8UHg)
