Javascript 實現計算器:
系列文章:
JS 實現計算器詳解及實例代碼(一)
Javascript 實現計算器時間功能詳解及實例(二)
小型JavaScript計算器
自己尋思出的解決方案,比較笨拙的方法,雖然完成了但是還有不少bug,用的方法也不是最有效的,基本功能算是完成了,一些小的細節地方也考慮到了,但是還有其他的細節需要處理。
總體設計思路是,先畫草圖 -> 設計UI -> 編寫UI代碼 -> 編寫CSS -> 編寫JS邏輯代碼;
面板(main-board)
面板整體尺寸設計
標題欄(board-title)
屏顯區(board-result)
按鈕區(board-keys),使用表格完成,然後給每個td添加onclick事件
完成界面
導入新字體
// main.css @font-face { font-family: Lovelo-Black;/×定義font的名字×/ src: url('font/Lovelo Black.otf');/*把下載的字體文件引入進來×/ }
代碼分析
代碼組織結構
計算器對象:Calculator;
計算器屬性:
計算器方法:
輔助方法
代碼邏輯
使用方法
計算器對象
// 計算器對象 function Calculator() { // 私有屬性 this.bdResult = $("board-result"); // 計算機面板結果顯示區對象 this.operator = ['+', '-', '×', '÷', '=']; this.digits = ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '.']; // 組成有效數字的數字數組 this.dot = '.'; this.equal = '='; this.zero = '0'; this.digit = ""; // 當前輸入的數字 this.expression = ""; // 表達式 this.resSpan = getResSpan(); // 數字顯示區 this.resDown = $("result-down"); // 表達式顯示區 this.last = ""; // 上一次按下的按鈕內容 this.allDigits = []; // 從表達式中獲取的所有數字組成的數組,將用來和ops中的操作符對應計算出結果 this.ops = []; // 所有操作符組成的數組 this.hasEqual = false; // 判斷是否按下了'='鍵 this.lastRes = 0; // 上一次計算的結果,即上一次按等號後計算出的值 // 私有方法 }
添加點擊事件(注意this在閉包裡的引用問題)
// 為td添加點擊事件 Calculator.prototype.addTdClick = function () { var tds = $tag("td"); var that = this; // 需要注意保存this的引用 // 為每個td添加點擊事件 for (var i = 0; i < tds.length; i++) { tds[i].onclick = function (){ // alert(this.innerText); var text = this.innerText; that.calculatorClickEvent(text); }; } };
計算器點擊事件處理入口
// 計算器按鈕事件 Calculator.prototype.calculatorClickEvent = function (btnText) { // 上一個按鍵是'=' if (this.hasEqual) { this.hasEqual = false; this.clearData(); } // 結果顯示在board-result裡 if (btnText != "AC" && btnText != "CE") { this.btnClickHanlder(btnText); } else { // AC或CE清零 this.clearData(); } };
計算器點擊事件處理程序
// 計算器的按鍵事件處理 Calculator.prototype.btnClickHanlder = function (btnText) { if ((btnText >= '0' && btnText <= '9') || btnText == this.dot) { // 數字鍵處理 // 如果上一個是操作符,則清空當前數字區 if (this.isOperator(this.last)) { this.resSpan.innerText = ''; this.digit = ''; } else if ((btnText == this.dot) && (this.last == this.dot)) { // 如果上一個也是點,則對本次的點按鈕不做響應 return; } this.digit += btnText; this.expression += btnText; } else if (this.isOperator(btnText)) { // 操作符處理 // 如果當前表達式為'0',按'=',不給響應 if ((btnText == this.equal) && (this.resDown.innerText == this.zero || this.resDown.innerText == "")) return; // 如果上一個是非'='的操作符則不進行處理 if (!this.isOperator(this.last) && btnText == this.equal) { // '='處理 this.showCurrRes(this.zero, this.expression + btnText); // 計算結果顯示在表達式區域 return; } else if (this.isOperator(this.last)) { // 上一個是操作符,此次的操作符不做記錄 return; } else { this.expression += btnText; } } this.showCurrRes(this.digit, this.expression); this.last = btnText; };
處理將要顯示的表達式和當前輸入的數字
// 顯示當前結果的觸發方法 Calculator.prototype.showCurrRes = function (digit, expression) { if (!expression) return; this.showText(digit, expression); // 1. 沒有'=',表示還沒有到計算結果的時候,直接退出 if (expression.indexOf(this.equal) == -1) return; // 計算出了結果 this.hasEqual = true; // 2. 處理只按了數字然後直接按了等號的情況,即:'234='則直接返回234 var tmpStr = this.delHeadZero(expression.substr(0, expression.length - 1)); // 去掉最後一個'=' if (!this.hasOperator(tmpStr)) { this.showText(tmpStr, expression + tmpStr); return; } // 3. 處理表達式字符串,且計算出結果 var start = 0; for (var i = 0; i < expression.length; i++) { var c = expression[i]; if (this.isOperator(c)) { // 操作符 this.ops.push(c); // 保存操作符 var numStr = expression.substr(start, i + 1); // 數字字符串 var number = 0; // 浮點數和整型處理 if (numStr.indexOf(this.dot)) { number = parseFloat(numStr); } else { number = parseInt(numStr); } this.allDigits.push(number); // 保存數字 start = i + 1; // 重設數字起始位置,即操作符的下一個字符開始 } } // 用allDigits和ops去計算結果 var res = this.calResult(); // 保存此次計算結果,作為下一次計算用 [TODO] this.lastRes = res; // 將結果顯示出來 this.showText(res + '', expression + res); };
將處理結果顯示到屏顯區
// 將表達式和計算結果顯示到屏顯區 Calculator.prototype.showText = function (digitStr, expression) { // 先刪除開頭的'0' var expStr = this.delHeadZero(expression); var digStr = this.delHeadZero(digitStr); // 然後再根據情況決定是否添加'0' var tmp = expression == this.zero ? expression : this.addZero(expStr);; var dig = digitStr == this.zero ? digitStr : this.addZero(digStr); this.resSpan.innerText = dig; // 如果表達式第一個是操作符,則表示之前按的是'0',則給補上'0',因為前面將開頭的'0'都刪掉了 if (this.isOperator(tmp[0])) { tmp = this.zero + tmp; } this.resDown.innerText = tmp; }
計算結果函數
// 計算結果 Calculator.prototype.calResult = function () { var first = 0; var second = 0; var res = 0; for (var i = 0; i < this.ops.length; i++) { first = this.allDigits[i]; second = this.allDigits[i + 1]; switch (this.ops[i]) { case '+': res = first + second; break; case '-': res = first - second; break; case '×': res = first * second; break; case '÷': res = first / second; break; default: break; } this.allDigits[i + 1] = res; } return res; };
清空數據
// 計算完一次,清空所有數據,以備下次計算使用 Calculator.prototype.clearData = function () { this.allDigits = []; this.ops = []; this.expression = this.zero; this.digit = ''; this.resSpan.innerText = this.zero; this.resDown.innerText = this.zero; };
輔助函數
處理表達式開頭的'0'問題(第一個按鈕是0鍵或者第一個是小於1的浮點數,表達式需要補零;)
// 開頭添加'0',防止重復出現或者沒有'0'情況 Calculator.prototype.addZero = function (expression) { if (!expression) return this.zero; if (expression[0] == this.dot) { // 浮點數 return this.zero + expression; } else { return expression; } };
開頭去零函數
// 去開頭的零 Calculator.prototype.delHeadZero = function (str) { // 先把開頭的‘0'都刪掉 var tmp = ""; tmp = str.replace(/^[0]+/gi, ""); if (tmp[0] == this.dot) { // 浮點數重新補上'0' tmp = this.zero + tmp; } return tmp; };
判斷字符串裡是否含有操作符
// 判斷表達式中是否含有操作符 Calculator.prototype.hasOperator = function (str) { if (!str) return; for (var i = 0; i < this.operator.length; i++) { if (str.indexOf(this.operator[i]) >= 0) { return true; } } return false; };
其他函數
// 獲取輸入的數字顯示區對象 function getResSpan() { return $("result-up").getElementsByTagName("span")[0]; } // 根據標簽名獲取DOM對象 function $tag(tagName) { return document.getElementsByTagName(tagName); } // 根據ID獲取DOM對象 function $(id) { return document.getElementById(id); }
問題
感謝閱讀,希望能幫助到大家,謝謝大家對本站的支持!