第 04 章 - 使用 if 與 switch 進行邏輯判斷
上次更新日期 2020/09/22
所謂的『邏輯判斷』就是透過前一章節討論的布林值所回傳的真與假 (true and false) 作為判斷依據,如果狀態為真,那就進行事件一, 如果狀態為假,那就進行事件二這樣。透過邏輯判斷,我們就可以讓系統做個比較有趣的變化了。
學習目標:
- 了解邏輯判斷式
- 了解流程圖的圖示意義
- 實際操作 if 程式
- 實際操作 switch 程式
- 數值函數的亂數與整數應用
4.1: 邏輯判斷式
其實前一章的布林值變數型別裡面我們就曾經講到邏輯判斷了,就是透過底下的方式來取得邏輯判斷的回傳值為 true 或 false
var logic1 = ( bmi > 24 );
此時 logic1 只會取得 true 或 false 這種布林值型別的值而已。所以說,邏輯運算就是答案為『 true 』或『 false 』的運算啊! 一般的邏輯運算式,大致是這樣的:
變數或常數 關係運算 變數或常數 A > 15 B <= 12 變數或常數 等於運算 變數或常數 S == Q Y != Q
你可以看到關係運算主要就是大於等於小於之類的符號,至於驚嘆號 (!) 有『不是、反向』選擇的意思,這些運算都只會回傳 true 或 false 喔! 因為是邏輯運算啊!
- 複合邏輯計算
如果要同時滿足兩個以上的條件才邏輯判斷為真,那就是我們以前學數學所謂的 and 囉!如果是兩個條件的任何一個成立時,就會回傳值為真, 那就是 or 囉!例如前一章提到的 BMI 計算結果:
var bmi; ( bmi > 18.5 ) && ( bmi < 24 ) // BMI 需要同時大於 18.5 與小於 24 才是真 ( bmi < 18.5 ) || ( bmi > 24 ) // BMI 小於 18.5 或者是大於 24 都可接受為真
所以,這個時候 && 以及 || 的協助就非常重要了!另外,邏輯判斷完畢之後,當然重點就是得要設計『當回傳 true 時,要進行什麼事? 而當回傳 false 時,則是進行另外的什麼事』這樣。那如何設計這方面的程式呢?這時最好先要有流程圖的概念:
- 流程圖圖示
一般來說,流程圖慣用的圖示樣式與代表的意義有點像這樣:
舉例來說,要判斷你的 BMI 指數是否合於正常範圍,那可以這樣設計:
也就是透過邏輯判斷出 BMI 有沒有超出 18.5~24 之間的範圍,在此範圍內 (true) 就以身體素質正常進行程式運作, 若不在此範圍內 (false),就使用其他程序進行,讓填寫者確認自己的身體狀況可能可以怎麼改善比較妥當之類的。 這時就可以搭配程式來將各個流程圖內的資料完整化了。
4.2: 使用 if 進行條件判斷
使用 if 進行邏輯判斷,主要的語法是這樣的:
if (邏輯判斷) { // 當回答為 true 時的工作 ... }
但是,總有邏輯判斷總有真假吧?所以,如果真假兩件事分別依據邏輯判斷回應值而進行的話,就會變這樣:
if (邏輯判斷) { // 當回答為 true 時的工作 程式碼... } else { // 當回答為 false 時的工作 程式碼... }
那如果有多個選項呢?基本上可以透過多重邏輯判斷的,例如:
if (邏輯判斷-1) { // 當邏輯判斷-1 回答為 true 時的工作 程式碼... } else if (邏輯判斷-2) { // 當邏輯判斷-2 回答為 true 時的工作 程式碼... } else { // 當邏輯判斷-1 與 邏輯判斷-2 回答都是 false 時的工作 程式碼... }
- 建立 unit04-2-1.php 檔案,並且在index.php 裡面加上相關的超連結,target 指向 js 視窗。
- 使用 這個檔案 的內容貼上 unit04-2-1.php 當中。
- 如同檔案內的設定,建立 ansbmi 函數,並且同時判斷兩個同時成立的邏輯運算 (&&),亦即 bmi >=18.5 與 bmi <=24 的情況:
- 若回傳為 true 時,顯示訊息 (可以設定一個變數處理) 為:『體重狀態很優良啊!』
- 若回傳為 false 時,顯示訊息為:『體重的狀態不是很好喔!』
若只有真與假,那使用 if () {} else {} 即可,但如果一個判斷裡面有多種狀態呢?例如上面 BMI 的案例中,如果有體重過輕 ( BMI < 18.5)、 體重優良 (18.5 ≤ BMI < 24)、體重稍重 (24 ≤ BMI < 28) 與肥胖 (28 ≤ BMI)等,那處理的方案就得要使用多重狀態, 亦即增上多個 else if 即可喔!
- 將 unit04-2-1.php 另存新檔成為 unit04-2-2.php,並且在index.php 裡面加上相關的超連結,target 指向 js 視窗。
- 透過 if ... else if 的功能,將回傳的訊息增加為 4 種狀態,亦即過輕、正常、稍重與肥胖。
- 使用 if 設計 UI 界面
如下圖,假設我們需要計算面積,而且需要依據不同的形狀來提供使用者輸入的資訊,這該如何設計?最簡單,就是將所有需要出現的, 通通給它放上來即可。問題是,這樣對於使用者的提示來說,好像有點混亂。
所以,我們是否能夠依據使用者點選不同的面積時,才出現所需要的 input 資訊?然後提供計算的結果呢? 似乎可以透過 if 的方式,當使用者點選相關的形狀後,再來使用 innerHTML 處理吧!設計看看:
- 建立 unit04-2-3.php 檔案,並且在index.php 裡面加上相關的超連結,target 指向 js 視窗。
- 使用 這個檔案 的內容貼上 unit04-2-3.php 當中,並且先查看應用一下該網頁。
- 先增加 label 的功能,讓使用者點選形狀的字體時,也能夠勾選單選項目。
- 將兩個數值的 input 取消,然後增加兩個 div,其 id 分別為 inp1 與 inp2 好了, 這兩個 div 是預計作為等等是否需要有兩個輸入框的預留環境
- 開始設計 myselect() 函數:
- 由於我們的 form 使用了 myform 為 id,因此先設定一個變數名稱為 myform ,並且用以取得 id 為 myform 的表單元素。
- 設計一個名為 myselect 的變數,內容為 myform.sel.value 這個單選資料 (請注意 form 大部分只對 input 有父、子關係!
- 分別設計兩變數,分別是 inp1, inp2,分別取得 inp1 與 inp2 這兩個 id 的元素資訊
- 判斷 myselect 是否為 1, 2, 3 等不同的數據,根據不同的數據來填寫 inp1.innerHTML 與 inp2.innerHTML, 就可以處理不同形狀的輸入框了。
- 設計完成之後,當你點選不同的形狀時,畫面應該會出現相對應的輸入框才對,如下所示:
- 開始設計 mycal() 函數:
- 一樣設計 myform 變數,取得 myform 頂層表單元素
- 一樣設計 myselect 變數,內容為 myform.sel.value 即可。
- 當 myselect == "1" 時,將 myform.num1.value 轉為數值後,使用 πr2 計算面積
- 當 myselect == "2" 時,將 myform.num{1|2}.value 轉為數值後,使用 (1/2底*高) 計算面積
- 當 myselect == "3" 時,將 myform.num{1|2}.value 轉為數值後,使用 (長*寬) 計算面積
- 將計算完畢的面積丟入 myform.ans.value 當中。
上面的習題中,因為使用了 myform 的頂層表單 id,因此許多的單選、文字輸入框就可以直接透過 myform 的取得。 如果今日你只想要取出某個元素,並不要依附在頂層表單時,例如單純想要取得單選 radio 的 input 狀態時 , 也能透過類似 mysel = document.getElementsByName('sel') 來取得陣列值喔!而這種單選的陣列,可以透過 checked = {true|flase} 來抓取數值的。
4.3: 使用 switch 進行條件判斷
透過 if 的協助,我們可以判斷很多不同的狀態,真是萬用的功能。不過,如果我們的判斷式其實只有一個變數或者是簡單的邏輯資訊, 那似乎可以透過數值切換 (switch) 的語法功能來處理,讓整體程式看起來更簡單。switch 的語法有點像這樣:
switch (變數或狀態) { case "數值或字串-1" : 程式碼... break; case "數值或字串-2" : 程式碼... break; .... default : 程式碼... break; }
整體程式由 switch 與邏輯運算開始,然後每個『值或字串』就放在 case 與冒號 (:) 當中,在底下就接需要的程式碼。離開該段程式碼, 則輸入中斷 (break;) 離開 switch。至於最後都不在規範內的數值,則以 default (預設值) 來處理掉。
- 將 unit04-2-3.php 另存新檔為 unit04-3-1.php,並且在index.php 裡面加上相關的超連結,target 指向 js 視窗。
- 將 if 的語法改為 switch 的語法來處理即可。
整個畫面與 unit04-2-3.php 的呈現結果是相同的,不過,在語法的可讀性上面,會稍微好一點點,至少括號 { } 會少掉很多! 這樣閱讀起來會稍微好一些。不過也要同時注意, case 後面接的資料,應該只能是字串或整數會比較好!
4.4: 數值函數的亂數與整數應用
很多時候網頁上面可能會需要『隨機產生某些東西』的情境,這些情境就得要使用所謂的亂數來處理。 JavaScript 提供了一個數學函數,稱為 Math (注意 M 為大寫),這個 Math 函數的 .random() 就可以取得一個 0~0.9999... 之間的數值, 這就是亂數!如果想要取得一個 0~5 之間的亂數,就得要:
var myrand = Math.random() * 5;
不過你要注意的是, random() 給的是浮點數,並不是整數喔!如果需要整數,可以透過數值的 .floor() 來進行整數的『無條件捨去』法! 基本上, Math 提供的小數進位法有底下基本的三種:
Math.floor(value) // 無條件捨去 Math.round(value) // 四捨五入法 Math.ceil(value) // 無條件進位
一般來說,如果是需要整數的亂數,通常使用的就是無條件捨去法 (.floor()) 來處理的!例如,我們要取得 1~6 之間的 6 個整數, 不能只是 Math.random() * 6 然後取取無條件捨去,因為這樣會變成 0~5 之間...所以才需要 +1 喔!
- 建立新檔為 unit04-4-1.php,並在 index.php 裡面加上相關的超連結,target 指向 js 視窗。
- 使用 這個檔案 的內容貼上 unit04-4-1.php 當中,並且先查看應用一下該網頁。
- 設計 pcgo() 函數:
- 這個函數的目的是要取得三個骰子的亂數,所以,先設定 pcform 這個變數來取得 pcform 這個表單元素
- 使用 pcform.pc1.value = Math.floor(Math.random()*6)+1; 取得第一個骰子的值
- 繼續將後續 pc2, pc3 的骰子也放上去。
- 設計 onload 功能:這個 pcgo() 必須亦按下按鈕才能夠進行,實在有點怪。我們讓整個網頁載入完成之後就主動執行這個函數, 可以在 <body > 裡面增加『 onload='pcgo()' 』,就可以在網頁開啟完畢後,立刻執行 pcgo() 了!看一下網頁會變這樣:
- 設計 mygo() 函數內容:
- 設計 myform 變數來取得 myform 表單元素
- 使用 myform.my1.value = Math.floor(Math.random()*6)+1; 取得骰子的值,並依序處理後續兩個骰子
- 取得 pcform 元素,並且將 pc1, pc2, pc3 數值相加,假設為 pcnu 變數為其總和
- 將 my1, my2, my3 數值相加,假設成為 mynu 總和結果
- 取得 ans 元素
- 使用 if 功能判斷 mynu 是否 (1)小於 (2)大於 (3)等於 pcnu,並給予不同的結果訊息,放置於 ans.innerHTML 當中。
- 簡單的 UI 設計
上面 4-4-1 例題有些地方怪怪的!電腦一開始骰下去得到結果之後,就不能改變了!那使用者反而可以多次擲骰子! 這與一般狀態好像不太一樣!平時玩擲骰子遊戲,都是莊家/閒家輪流擲骰子的,那如何輪流擲出骰子呢?其實很簡單! 讓使用者不能按按鈕就好了! input 標籤有個特別的屬性『 disabled 』,在 javascript 裡面可以設定為 true 與 false 呢! 你可以設計看看:
- 將 unit04-4-1.php 另存新檔為 unit04-4-2.php,並在 index.php 裡面加上相關的超連結,target 指向 js 視窗。
- 修改 pcgo() 函數:
- 取得 myform 元素,並且設計 myform.myinp.disabled = false 且 pcform.myinp.disabled 為真
- 取得 ans 元素,並將 ans 的 innerHTML 設定為空字串,結果會像底下這樣:
- 修改 mygo() 函數:
- 將剛剛 pcgo() 函數的 disabled 狀態反轉即可。
這樣算是比較合乎使用者的一般操作行為吧!
4.5: 課後作業
- onclick 與 onsubmit 的差異
一般來說,如果是『按下這個按鈕,只有本身想做的元件會做事,並不會將資料上傳到其他地方去』時,使用的就是 onclick 的資訊。 不過,我們填寫表單 (form) 之後,通常是會按下傳送 (submit) 的,這個 submit 預設就會將資料上傳出去,而不論你的填寫資料是否成功。 這個情況的問題是,可能我們某些輸入框寫錯或者是忘記寫,會導致某些錯誤啊!
因此,再傳送前,確認一下資料有沒有問題,當沒有問題後,接受到函數回傳值為 true 時,就開始順利上傳, 如果有任何問題,就直接將表單的上傳行為停止!這樣就比較不會讓使用者反彈!
為了處理這個問題,因此需要修改表單資料,通常修改的位置就是在 <form> 裡面喔!大概有點像這樣:
<form onsubmit='return somefunction()' /> .... </form>
- element.focus() 的應用
承上,那如果你的 javascript 確認了某一個輸入框有問題的時候,是否能夠指引使用者到那一個輸入框去修改呢? 應該是這樣比較好吧!如果要這樣做,那就得要使用『 .focus() 』這個功能了!如果要移動到某個 id='myid' 的元素去, 就可以這樣:
document.getElementById('myid').focus();
知道了這幾個常用的資料,搭配 if 的語法,開始底下的實做練習吧!
- 使用 這個檔案的內容 作為主要的表單資訊, 並建立 unit04-5-1.php 的檔案,同時也在 index.php 裡面增加一筆連結記錄。
- 查看一下 unit04-5-1.php 的內容。
前處理準備好之後,開始來處理一些基礎資訊。
- 先將 <form ...> 的內部,增加如上講的『 onsubmit='return mycheck()' 』之類的函數,請注意, mycheck() 是可變的,只是在這裡作為一個簡介而已。另外,在 input type='submit' 的按鈕中, 千千萬萬不要設定 onclick 喔!否則可能會衝突。
- 建立檢查的函數,大致的流程有點像是這樣:
- 先抓取 myform 這個元素
- 檢查 myform.myaccount.value.length 整體輸入的字串長度是否大於等於 5,若小於 5 個字元時:
- 使用 innerHTML 將訊息丟進 myaccountid 那個元素內
- 將游標 focus 在 myform.myname 那個輸入框上面
- 回傳 false 的結果。
- 檢查 myname 是否大於等於 3 個字元以上,若小於 3 個字元,使用與上述相同方式來回傳 false
- 檢查 mytel 的長度是否一定等於 11 個字元,使用的格式為 0900-123456 這樣的格式,不過在本章的環境下, 只需要檢查長度是否剛剛好為 11 個字元即可。若不是 11 個字元,則使用與上述相同的方式來回傳 false
- 檢查 mygender 是否沒有選擇 (就是值是空字串),若沒有選擇,則回傳沒有填寫,然後依據上述的方式回傳 false。