前言
這篇文章將會把重點放在兩個部分:
eval()
函式- 正規式 (Regular Expression)
在寫這個題目以前,我沒有實際使用過正規式,這個概念大概是一個月以前才接觸的,最後雖然是有把功能寫出來,但是品質還有待加強,不過有小小進步這個挑戰很值得了,日後找機會再加強相關知識吧!
關卡資訊
- 【特定技術】數字位數過多時,不能因此而破版,計算機功能皆須齊全
- 【自我學習】請在此關卡中「自學一個你原本不太會的技巧」,投稿時分享你透過哪些資源學習,並寫範例程式碼講解該技巧,以及你如何應用在此關卡上。
eval()
語法
eval(string)
實例
可帶入一組字串,並執行字串中的 JavaScript 程式碼,且程式碼內可以包含變數及已存在物件的屬性。
1 | eval('2 + 2') // 4 |
如果 eval() 的參數不是字串,它將會將參數原封不動的返回該參數。
1 | eval(new String("2 + 2")); // String {"2 + 2"} |
如果要避免這個情況你可以先將參數進行轉字串的處理
1 | var expression = new String("2 + 2"); |
本次關卡應用
在了解 eval()
的用法後,可以開始思考開如何運用在計算機這個題目中?
數字及運算符號功能
我們可以先宣告一組字串,代表計算機等待被計算的算式。
1 | let formula = '' |
當我們按下按鍵後,應該要為 formula
字串增加該按鈕的值。為了達到這點,所有的數字按鍵和加減乘除都需要新增事件監聽。
1 | <div class="button">0</div> |
1 | document.querySelectorAll('.button').forEach((item) => { |
可以開啟這個 domo 操作一下,試著打一些簡單的加減乘除計算,再到 console 觀察 formula
變數的改變。到這個階段還有一個問題是可能會有一些不合規格的算式出現,如 1+÷1
這種無法被計算的情況,這就需要留到後面用正規式處理了。
接著繼續新增剩下的按鈕功能
= 功能
在使用者按下等於按鈕時將 formula
變數帶入 eval()
函數中,並將回傳值帶入 result
變數,也就是之後會渲染在計算機上的答案。
1 | <div class="equal">=</div> |
1 | let result; |
AC 功能
清空功能最單純,按下後將 formula
變數改為空字串即可。
1 | <div class="ac">AC</div> |
1 | document.querySelector('.ac').addEventListener('click', function(){ |
⌫ 功能
點擊回上一步後,將 formula
字串的最後一個字元刪除。
做法是先用 split('')
將 formula
字串轉為陣列,舉例說如果 formula 當前值為 1+1
,經過 split('')
處理會變成陣列['1', '+', '1']
,再用 pop()
將陣列最後一元素移除,然後再透過 join('')
轉回字串,結果 formula
由 1+1
變成了 1+
。
1 | <div class="del">⌫</div> |
1 | document.querySelector('.del').addEventListener('click', function(){ |
到這裡所有按鈕的功能告一段落,可以用這個 Demo 操作看看。接著我們來講講如何用正規式來篩選掉不合計算機規則的算式。
使用正規式過濾掉不合法的算式排列
如果對於正規式還不熟的朋友可以參考初探正規式這篇。
正規式是用來做什麼的呢?
正規式也可稱正則表達式、正規表達式…etc,我自己對於它的第一個印象是,這..是機器語言吧? 不覺得它是我能理解的東西,不過我們需要拋開偏見和恐懼,可以試著先去接觸看看,你會發現它是一個很棒的工具。
舉個正規式常見的應用,當我們在註冊某些網站的帳號時,為什麼當我們再輸入 Email 時,這個網站都會提醒我的 Email 格式是正確或是錯誤的,它是怎麼判斷的呢?其實這就是利用正規式來做檢測的,請參考[Javascript] Regular Expression – Email 表單驗證。
替換乘除符號
剛剛我們在實作時有一個小問題,當我們點擊 ÷
和 ×
時,會直接將這兩個字元帶入 formula
變數中,若變數值為 6÷2
,按下 =
按鈕後,變數被帶入 eval()
函式處理,結果拋出錯誤 "SyntaxError: Invalid or unexpected toke
,原因是 eval()
函式是不認得 ×÷
符號的,我們需要處理一下當使用者按下 ×÷
時需要把它替換成 */
,試著用正規式來做吧。
1 | formula.replace(/\÷/g, `/`).replace(/\×/g, `*`); |
異常數字處理
我們還需要排除開頭一個零以上和開頭零後面接數字的狀況,舉例說像式 00123 + 01235
的算式是不合理的,必須要做處理。
1 | formula.replace(/^0[0-9]+/, `0`).replace(/([/*+-])0\d+/g, `$10`); |
異常運算符號排列處理
正常的算式中不會出現相連的運算符號,比如 1+-2
,或是運算符號出現在開頭的情況 + 123 + 321
。
1 | formula.replace(/^[/*+-]+/, ``).replace(/([/*+-])[/*+-]+/g, `$1`); |
異常小數點處理
接著是比較複雜一點的小數點處理
- 算式開頭不能有小數點
.123 + 123
- 不能有相連的小數點
1..23 + 8
- 不會有
00.123
這樣的情況 - 運算符號後面不能出現小數點
123 + .123
- 同一組數字不會出現第二個小數點
123.123.3
1 | function fn(formula) { |
千分位
最後需要套用千分位,把運算結果渲染到計算機上,如果數字是 10000
會被轉換成 10,000
。
1 | function toCurrency(formula) { |
到這邊計算機的功能差不多完成了,可以到最後的 Demo 試著操作看看,再來就剩下一些畫面和細節的處理,有興趣的話請參考完整版。