簡易的JS計(jì)算器實(shí)現(xiàn)代碼
看看手機(jī)中的計(jì)算器,分為普通計(jì)算器和科學(xué)計(jì)算器

自認(rèn)腦袋不夠大,就實(shí)現(xiàn)一個(gè)普通版本的吧(支持正負(fù)數(shù)加減乘除等基本連續(xù)的運(yùn)算,未提供括號(hào)功能)
看看圖示效果:

一、知識(shí)準(zhǔn)備
1+1 = ?
正常來說,我們看到這個(gè)表達(dá)式都知道怎么運(yùn)算,知道運(yùn)算結(jié)果
但計(jì)算機(jī)不一樣,計(jì)算機(jī)無法識(shí)別出這串表達(dá)式,它只能識(shí)別特定的規(guī)則:前綴表達(dá)式+ 1 1 或后綴表達(dá)式1 1 +
舉個(gè)栗子
(3 + 4) × 5 - 6 就是中綴表達(dá)式
- × + 3 4 5 6 前綴表達(dá)式
3 4 + 5 × 6 - 后綴表達(dá)式
所以為了實(shí)現(xiàn)程序的自動(dòng)運(yùn)算,我們需要將輸入的數(shù)據(jù)轉(zhuǎn)化為前綴或后綴表達(dá)式
前綴、中綴、后綴表達(dá)式的概念以及相互轉(zhuǎn)換方法在這里就不多說了,這篇博文 說得比較清楚了
所以,在這個(gè)計(jì)算器的實(shí)現(xiàn)中,采用了后綴表達(dá)式的實(shí)現(xiàn)方式,參考以上文章,重點(diǎn)關(guān)注這兩個(gè)算法:
與轉(zhuǎn)換為前綴表達(dá)式相似,遵循以下步驟:
(1) 初始化兩個(gè)棧:運(yùn)算符棧S1和儲(chǔ)存中間結(jié)果的棧S2;
(2) 從左至右掃描中綴表達(dá)式;
(3) 遇到操作數(shù)時(shí),將其壓入S2;
(4) 遇到運(yùn)算符時(shí),比較其與S1棧頂運(yùn)算符的優(yōu)先級(jí):
(4-1) 如果S1為空,或棧頂運(yùn)算符為左括號(hào)“(”,則直接將此運(yùn)算符入棧;
(4-2) 否則,若優(yōu)先級(jí)比棧頂運(yùn)算符的高,也將運(yùn)算符壓入S1(注意轉(zhuǎn)換為前綴表達(dá)式時(shí)是優(yōu)先級(jí)較高或相同,而這里則不包括相同的情況);
(4-3) 否則,將S1棧頂?shù)倪\(yùn)算符彈出并壓入到S2中,再次轉(zhuǎn)到(4-1)與S1中新的棧頂運(yùn)算符相比較;
(5) 遇到括號(hào)時(shí):
(5-1) 如果是左括號(hào)“(”,則直接壓入S1;
(5-2) 如果是右括號(hào)“)”,則依次彈出S1棧頂?shù)倪\(yùn)算符,并壓入S2,直到遇到左括號(hào)為止,此時(shí)將這一對(duì)括號(hào)丟棄;
(6) 重復(fù)步驟(2)至(5),直到表達(dá)式的最右邊;
(7) 將S1中剩余的運(yùn)算符依次彈出并壓入S2;
(8) 依次彈出S2中的元素并輸出,結(jié)果的逆序即為中綴表達(dá)式對(duì)應(yīng)的后綴表達(dá)式(轉(zhuǎn)換為前綴表達(dá)式時(shí)不用逆序)。
與前綴表達(dá)式類似,只是順序是從左至右:
從左至右掃描表達(dá)式,遇到數(shù)字時(shí),將數(shù)字壓入堆棧,遇到運(yùn)算符時(shí),彈出棧頂?shù)膬蓚€(gè)數(shù),用運(yùn)算符對(duì)它們做相應(yīng)的計(jì)算(次頂元素 op 棧頂元素),并將結(jié)果入棧;重復(fù)上述過程直到表達(dá)式最右端,最后運(yùn)算得出的值即為表達(dá)式的結(jié)果。
例如后綴表達(dá)式“3 4 + 5 × 6 -”:
(1) 從左至右掃描,將3和4壓入堆棧;
(2) 遇到+運(yùn)算符,因此彈出4和3(4為棧頂元素,3為次頂元素,注意與前綴表達(dá)式做比較),計(jì)算出3+4的值,得7,再將7入棧;
(3) 將5入棧;
(4) 接下來是×運(yùn)算符,因此彈出5和7,計(jì)算出7×5=35,將35入棧;
(5) 將6入棧;
(6) 最后是-運(yùn)算符,計(jì)算出35-6的值,即29,由此得出最終結(jié)果。
二、實(shí)現(xiàn)過程
第一步當(dāng)然是搭建計(jì)算器的頁面結(jié)構(gòu),不是科學(xué)計(jì)算器,只提供了基本的運(yùn)算功能,但也能即時(shí)地進(jìn)行運(yùn)算,顯示出完整的中綴表達(dá)式,運(yùn)算后保存上一條運(yùn)算記錄。
要先說一下:本來想實(shí)現(xiàn)小數(shù)點(diǎn)功能的,但小數(shù)點(diǎn)的存在讓數(shù)據(jù)存儲(chǔ)與數(shù)據(jù)顯示的實(shí)現(xiàn)有了壓力,實(shí)現(xiàn)過程實(shí)在腦大,索性先取消這個(gè)功能。
1. 頁面結(jié)構(gòu):
<h5>計(jì)算計(jì)算</h5>
<!-- 計(jì)算器 -->
<div class="calc-wrap">
<div class="calc-in-out">
<!-- 上一條運(yùn)算記錄 -->
<p class="calc-history" title=""></p>
<!-- 輸入的數(shù)據(jù) -->
<p class="calc-in"></p>
<!-- 輸出的運(yùn)算結(jié)果 -->
<p class="calc-out active"></p>
</div>
<table class="calc-operation">
<thead></thead>
<tbody>
<tr>
<td data-ac="cls" class="cls">C</td>
<td data-ac="del">←</td>
<td data-ac="sq">x<sup>2</sup></td>
<td data-ac="mul">×</td>
</tr>
<tr>
<td data-val="7">7</td>
<td data-val="8">8</td>
<td data-val="9">9</td>
<td data-ac="div">÷</td>
</tr>
<tr>
<td data-val="4">4</td>
<td data-val="5">5</td>
<td data-val="6">6</td>
<td data-ac="plus">+</td>
</tr>
<tr>
<td data-val="1">1</td>
<td data-val="2">2</td>
<td data-val="3">3</td>
<td data-ac="minus">-</td>
</tr>
<td data-ac="per">%</td>
<td data-val="0">0</td>
<td data-ac="dot">.</td>
<td data-ac="eq" class="eq">=</td>
</tbody>
</table>
</div>
2. 結(jié)合一點(diǎn)樣式:
body {
padding: 20px;
font-family: Arial;
}
.calc-wrap {
width: 300px;
border: 1px solid #ddd;
border-radius: 3px;
}
.calc-operation {
width: 100%;
border-collapse: collapse;
}
.calc-in-out {
width: 100%;
padding: 10px 20px;
text-align: right;
box-sizing: border-box;
background-color: rgba(250, 250, 250, .9);
}
.calc-in-out p {
overflow: hidden;
margin: 5px;
width: 100%;
}
.calc-history {
margin-left: -20px;
font-size: 18px;
color: #bbb;
border-bottom: 1px dotted #ddf;
min-height: 23px;
}
.calc-in,
.calc-out {
font-size: 20px;
color: #888;
line-height: 39px;
min-height: 39px;
}
.calc-in {
color: #888;
}
.calc-out {
color: #ccc;
}
.calc-in.active,
.calc-out.active {
font-size: 34px;
color: #666;
}
.calc-operation td {
padding: 10px;
width: 25%;
text-align: center;
border: 1px solid #ddd;
font-size: 26px;
color: #888;
cursor: pointer;
}
.calc-operation td:active {
background-color: #ddd;
}
.calc-operation .cls {
color: #ee8956;
}
這樣靜態(tài)的計(jì)算器就粗來了~~

3. JS邏輯
這部分就是重點(diǎn)了,一步步來說
首先是對(duì)計(jì)算器的監(jiān)聽吧,也就是這個(gè)表格,可以使用事件委托的方式,在父級(jí)節(jié)點(diǎn)上監(jiān)聽處理
// 綁定事件
bindEvent: function() {
var that = this;
that.$operation.on('click', function(e) {
e = e || window.event;
var elem = e.target || e.srcElement,
val,
action;
if (elem.tagName === 'TD') {
val = elem.getAttribute('data-val') || elem.getAttribute('data-ac');
監(jiān)聽數(shù)據(jù),獲取到的只是頁面上的某個(gè)值/操作符,所以需要將數(shù)據(jù)存儲(chǔ)起來形成中綴,再由中綴轉(zhuǎn)換成后綴,最后通過后綴進(jìn)行計(jì)算
// 中綴表達(dá)式
this.infix = [];
// 后綴表達(dá)式
this.suffix = [];
// 后綴表達(dá)式運(yùn)算結(jié)果集
this.result = [];
按照算法步驟,實(shí)現(xiàn)出來,這里沒有使用到括號(hào),如果實(shí)際需要,可在相應(yīng)位置修改判斷條件即可~
// 中綴表達(dá)式轉(zhuǎn)后綴
infix2Suffix: function() {
var temp = [];
this.suffix = [];
for (var i = 0; i < this.infix.length; i++) {
// 數(shù)值,直接壓入
if (!this.isOp(this.infix[i])) {
this.suffix.push(this.infix[i]);
}
else {
if (!temp.length) {
temp.push(this.infix[i]);
}
else {
var opTop = temp[temp.length - 1];
// 循環(huán)判斷運(yùn)算符優(yōu)先級(jí),將運(yùn)算符較高的壓入后綴表達(dá)式
if (!this.priorHigher(opTop, this.infix[i])) {
while (temp.length && !this.priorHigher(opTop, this.infix[i])) {
this.suffix.push(temp.pop());
opTop = temp[temp.length - 1];
}
}
// 將當(dāng)前運(yùn)算符也壓入后綴表達(dá)式
temp.push(this.infix[i]);
}
}
}
// 將剩余運(yùn)算符號(hào)壓入
while (temp.length) {
this.suffix.push(temp.pop());
}
},
// 后綴表達(dá)式計(jì)算
calcSuffix: function() {
this.result = [];
for (var i = 0; i < this.suffix.length; i++) {
// 數(shù)值,直接壓入結(jié)果集
if (!this.isOp(this.suffix[i])) {
this.result.push(this.suffix[i]);
}
// 運(yùn)算符,從結(jié)果集中取出兩項(xiàng)進(jìn)行運(yùn)算,并將運(yùn)算結(jié)果置入結(jié)果集合
else {
this.result.push(this.opCalc(this.result.pop(), this.suffix[i], this.result.pop()));
}
}
// 此時(shí)結(jié)果集中只有一個(gè)值,即為結(jié)果
return this.result[0];
}
其實(shí),在實(shí)現(xiàn)的時(shí)候會(huì)發(fā)現(xiàn),中綴、后綴只是一個(gè)難點(diǎn),更復(fù)雜的地方是整個(gè)計(jì)算器的狀態(tài)變化(或者說是數(shù)據(jù)變化)
在這個(gè)簡單的計(jì)算器中,就有數(shù)字(0-9)、運(yùn)算符(+ - * /)、操作(清除 刪除)、預(yù)運(yùn)算(百分號(hào) 平方)、小數(shù)點(diǎn)、即時(shí)運(yùn)算等數(shù)據(jù)及操作
如果是科學(xué)計(jì)算器那就更復(fù)雜了,所以理清如何控制這些東西很關(guān)鍵,而其中最重要的就是中綴表達(dá)式的構(gòu)建與存儲(chǔ)
當(dāng)連續(xù)點(diǎn)擊+號(hào)時(shí),是不符合實(shí)際操作的,所以需要一個(gè)變量 lastVal 來記錄上一個(gè)值,隨著操作而更新,再通過判斷,防止程序出錯(cuò)
在點(diǎn)擊=號(hào)之后,我們可以繼續(xù)使用這個(gè)結(jié)果進(jìn)行運(yùn)算,或者重新開始運(yùn)算
// 構(gòu)建中綴表達(dá)式
buildInfix: function(val, type) {
// 直接的點(diǎn)擊等于運(yùn)算之后,
if (this.calcDone) {
this.calcDone = false;
// 再點(diǎn)擊數(shù)字,則進(jìn)行新的運(yùn)算
if (!this.isOp(val)) {
this.resetData();
}
// 再點(diǎn)擊運(yùn)算符,則使用當(dāng)前的結(jié)果值繼續(xù)進(jìn)行運(yùn)算
else {
var re = this.result[0];
this.resetData();
this.infix.push(re);
}
}
var newVal;
...
點(diǎn)擊刪除,是刪除一位數(shù),不是直接地刪除一個(gè)數(shù),然后更新中綴表達(dá)式的值
// 刪除操作
if (type === 'del') {
newVal = this.infix.pop();
// 刪除末尾一位數(shù)
newVal = Math.floor(newVal / 10);
if (newVal) {
this.infix.push(newVal);
}
this.lastVal = this.infix[this.infix.length - 1];
return this.infix;
}
而添加操作,要考慮的就更多了,比如連續(xù)的連續(xù)運(yùn)算符、連續(xù)的數(shù)字、運(yùn)算符+ - 接上數(shù)字表示正負(fù)數(shù),小數(shù)點(diǎn)的連接存取等
// 添加操作,首先得判斷運(yùn)算符是否重復(fù)
else if (type === 'add') {
// 兩個(gè)連續(xù)的運(yùn)算符
if (this.isOp(val) && this.isOp(this.lastVal)) {
return this.infix;
}
// 兩個(gè)連續(xù)的數(shù)字
else if (!this.isOp(val) && !this.isOp(this.lastVal)) {
newVal = this.lastVal * 10 + val;
this.infix.pop();
this.infix.push(this.lastVal = newVal);
return this.infix;
}
// 首個(gè)數(shù)字正負(fù)數(shù)
if (!this.isOp(val) && this.infix.length === 1 && (this.lastVal === '+' || this.lastVal === '-')) {
newVal = this.lastVal === '+' ? val : 0 - val;
this.infix.pop();
this.infix.push(this.lastVal = newVal);
return this.infix;
}
this.infix.push(this.lastVal = val);
return this.infix;
}
在很多次操作的時(shí)候,計(jì)算器都需要即時(shí)地進(jìn)行運(yùn)算,為簡化代碼,可以封裝成一個(gè)方法,在相應(yīng)的位置調(diào)用即可
// 即時(shí)得進(jìn)行運(yùn)算
calculate: function(type) {
this.infix2Suffix();
var suffixRe = this.calcSuffix();
if (suffixRe) {
this.$out.text('=' + suffixRe)
.attr('title', suffixRe)
.removeClass('active');
// 如果是直接顯示地進(jìn)行等于運(yùn)算
if (type === 'eq') {
this.$in.removeClass('active');
this.$out.addClass('active');
// 設(shè)置標(biāo)記:當(dāng)前已經(jīng)顯示地進(jìn)行計(jì)算
this.calcDone = true;
this.lastVal = suffixRe;
// 設(shè)置歷史記錄
var history = this.infix.join('') + ' = ' + suffixRe;
this.$history.text(history).attr('title', history);
}
}
},
剩下的就是點(diǎn)擊之后的處理過程了,也就是各種調(diào)用處理 傳遞數(shù)據(jù)->構(gòu)建中綴處理數(shù)據(jù)->中綴轉(zhuǎn)后綴->后綴運(yùn)算顯示
比如點(diǎn)擊了數(shù)字
// 數(shù)字:0-9
if (!isNaN(parseInt(val, 10))) {
// 構(gòu)建中綴表達(dá)式并顯示
var infixRe = that.buildInfix(parseInt(val, 10), 'add');
that.$in.text(infixRe.join('')).addClass('active');
that.calculate();
return;
}
又比如幾個(gè)預(yù)運(yùn)算,其實(shí)長得也差不多
// 預(yù)運(yùn)算:百分比、小數(shù)點(diǎn)、平方
else if (['per', 'dot', 'sq'].indexOf(action) !== -1) {
if (!that.infix.length || that.isOp(that.lastVal)) {
return;
}
if (action === 'per') {
that.lastVal /= 100;
} else if (action === 'sq') {
that.lastVal *= that.lastVal;
} else if (action === 'dot') {
// that.curDot = true;
}
// 重新構(gòu)建中綴表達(dá)式
var infixRe = that.buildInfix(that.lastVal, 'change');
that.$in.text(infixRe.join('')).addClass('active');
that.calculate();
}
以上就是這個(gè)簡單計(jì)算器的實(shí)現(xiàn)步驟了,變化太多還不敢保證不會(huì)出錯(cuò)
基本邏輯如此,如果要加上小數(shù)點(diǎn)運(yùn)算、括號(hào)運(yùn)算、正余弦等科學(xué)計(jì)算器的功能,還是自己去實(shí)現(xiàn)吧。。腦大啊。。
$(function() {
function Calculator($dom) {
this.$dom = $($dom);
// 歷史運(yùn)算
this.$history = this.$dom.find('.calc-history');
// 輸入?yún)^(qū)
this.$in = this.$dom.find('.calc-in');
// 輸出區(qū)
this.$out = this.$dom.find('.calc-out');
this.$operation = this.$dom.find('.calc-operation');
// 運(yùn)算符映射
this.op = {
'plus': '+',
'minus': '-',
'mul': '*',
'div': '/'
};
this.opArr = ['+', '-', '*', '/'];
// 中綴表達(dá)式
this.infix = [];
// 后綴表達(dá)式
this.suffix = [];
// 后綴表達(dá)式運(yùn)算結(jié)果集
this.result = [];
// 存儲(chǔ)最近的值
this.lastVal = 0;
// 當(dāng)前已經(jīng)計(jì)算等于完成
this.calcDone = false;
// 當(dāng)前正在進(jìn)行小數(shù)點(diǎn)點(diǎn)(.)相關(guān)值的修正
this.curDot = false;
this.init();
}
Calculator.prototype = {
constructor: Calculator,
// 初始化
init: function() {
this.bindEvent();
},
// 綁定事件
bindEvent: function() {
var that = this;
that.$operation.on('click', function(e) {
e = e || window.event;
var elem = e.target || e.srcElement,
val,
action;
if (elem.tagName === 'TD') {
val = elem.getAttribute('data-val') || elem.getAttribute('data-ac');
// 數(shù)字:0-9
if (!isNaN(parseInt(val, 10))) {
// 構(gòu)建中綴表達(dá)式并顯示
var infixRe = that.buildInfix(parseInt(val, 10), 'add');
that.$in.text(infixRe.join('')).addClass('active');
that.calculate();
return;
}
action = val;
// 操作:清除、刪除、計(jì)算等于
if (['cls', 'del', 'eq'].indexOf(action) !== -1) {
if (!that.infix.length) {
return;
}
// 清空數(shù)據(jù)
if (action === 'cls' || (action === 'del' && that.calcDone)) {
that.$in.text('');
that.$out.text('');
that.resetData();
}
// 清除
else if (action === 'del') {
// 重新構(gòu)建中綴表達(dá)式
var infixRe = that.buildInfix(that.op[action], 'del');
that.$in.text(infixRe.join('')).addClass('active');
that.calculate();
}
// 等于
else if (action === 'eq') {
that.calculate('eq');
}
}
// 預(yù)運(yùn)算:百分比、小數(shù)點(diǎn)、平方
else if (['per', 'dot', 'sq'].indexOf(action) !== -1) {
if (!that.infix.length || that.isOp(that.lastVal)) {
return;
}
if (action === 'per') {
that.lastVal /= 100;
} else if (action === 'sq') {
that.lastVal *= that.lastVal;
} else if (action === 'dot') {
// that.curDot = true;
}
// 重新構(gòu)建中綴表達(dá)式
var infixRe = that.buildInfix(that.lastVal, 'change');
that.$in.text(infixRe.join('')).addClass('active');
that.calculate();
}
// 運(yùn)算符:+ - * /
else if (that.isOp(that.op[action])) {
if (!that.infix.length && (that.op[action] === '*' || that.op[action] === '/')) {
return;
}
var infixRe = that.buildInfix(that.op[action], 'add');
that.$in.text(infixRe.join('')).addClass('active');
}
}
});
},
resetData: function() {
this.infix = [];
this.suffix = [];
this.result = [];
this.lastVal = 0;
this.curDot = false;
},
// 構(gòu)建中綴表達(dá)式
buildInfix: function(val, type) {
// 直接的點(diǎn)擊等于運(yùn)算之后,
if (this.calcDone) {
this.calcDone = false;
// 再點(diǎn)擊數(shù)字,則進(jìn)行新的運(yùn)算
if (!this.isOp(val)) {
this.resetData();
}
// 再點(diǎn)擊運(yùn)算符,則使用當(dāng)前的結(jié)果值繼續(xù)進(jìn)行運(yùn)算
else {
var re = this.result[0];
this.resetData();
this.infix.push(re);
}
}
var newVal;
// 刪除操作
if (type === 'del') {
newVal = this.infix.pop();
// 刪除末尾一位數(shù)
newVal = Math.floor(newVal / 10);
if (newVal) {
this.infix.push(newVal);
}
this.lastVal = this.infix[this.infix.length - 1];
return this.infix;
}
// 添加操作,首先得判斷運(yùn)算符是否重復(fù)
else if (type === 'add') {
// 兩個(gè)連續(xù)的運(yùn)算符
if (this.isOp(val) && this.isOp(this.lastVal)) {
return this.infix;
}
// 兩個(gè)連續(xù)的數(shù)字
else if (!this.isOp(val) && !this.isOp(this.lastVal)) {
newVal = this.lastVal * 10 + val;
this.infix.pop();
this.infix.push(this.lastVal = newVal);
return this.infix;
}
// 首個(gè)數(shù)字正負(fù)數(shù)
if (!this.isOp(val) && this.infix.length === 1 && (this.lastVal === '+' || this.lastVal === '-')) {
newVal = this.lastVal === '+' ? val : 0 - val;
this.infix.pop();
this.infix.push(this.lastVal = newVal);
return this.infix;
}
// TODO: 小數(shù)點(diǎn)運(yùn)算
// if (this.isOp(val)) {
// this.curDot = false;
// }
// // 小數(shù)點(diǎn)
// if (this.curDot) {
// var dotLen = 0;
// newVal = this.infix.pop();
// dotLen = newVal.toString().split('.');
// dotLen = dotLen[1] ? dotLen[1].length : 0;
// newVal += val / Math.pow(10, dotLen + 1);
// // 修正小數(shù)點(diǎn)運(yùn)算精確值
// newVal = parseFloat(newVal.toFixed(dotLen + 1));
// this.infix.push(this.lastVal = newVal);
// return this.infix;
// }
this.infix.push(this.lastVal = val);
return this.infix;
}
// 更改操作,比如%的預(yù)運(yùn)算
else if (type === 'change') {
this.infix.pop();
this.infix.push(this.lastVal = val);
return this.infix;
}
},
// 判斷是否為運(yùn)算符
isOp: function(op) {
return op && this.opArr.indexOf(op) !== -1;
},
// 判斷運(yùn)算符優(yōu)先級(jí)
priorHigher: function(a, b) {
return (a === '+' || a === '-') && (b === '*' || b === '/');
},
// 進(jìn)行運(yùn)算符的運(yùn)算
opCalc: function(b, op, a) {
return op === '+'
? a + b
: op === '-'
? a - b
: op === '*'
? a * b
: op === '/'
? a / b
: 0;
},
// 即時(shí)得進(jìn)行運(yùn)算
calculate: function(type) {
this.infix2Suffix();
var suffixRe = this.calcSuffix();
if (suffixRe) {
this.$out.text('=' + suffixRe)
.attr('title', suffixRe)
.removeClass('active');
// 如果是直接顯示地進(jìn)行等于運(yùn)算
if (type === 'eq') {
this.$in.removeClass('active');
this.$out.addClass('active');
// 設(shè)置標(biāo)記:當(dāng)前已經(jīng)顯示地進(jìn)行計(jì)算
this.calcDone = true;
this.lastVal = suffixRe;
// 設(shè)置歷史記錄
var history = this.infix.join('') + ' = ' + suffixRe;
this.$history.text(history).attr('title', history);
}
}
},
// 中綴表達(dá)式轉(zhuǎn)后綴
infix2Suffix: function() {
var temp = [];
this.suffix = [];
for (var i = 0; i < this.infix.length; i++) {
// 數(shù)值,直接壓入
if (!this.isOp(this.infix[i])) {
this.suffix.push(this.infix[i]);
}
else {
if (!temp.length) {
temp.push(this.infix[i]);
}
else {
var opTop = temp[temp.length - 1];
// 循環(huán)判斷運(yùn)算符優(yōu)先級(jí),將運(yùn)算符較高的壓入后綴表達(dá)式
if (!this.priorHigher(opTop, this.infix[i])) {
while (temp.length && !this.priorHigher(opTop, this.infix[i])) {
this.suffix.push(temp.pop());
opTop = temp[temp.length - 1];
}
}
// 將當(dāng)前運(yùn)算符也壓入后綴表達(dá)式
temp.push(this.infix[i]);
}
}
}
// 將剩余運(yùn)算符號(hào)壓入
while (temp.length) {
this.suffix.push(temp.pop());
}
},
// 后綴表達(dá)式計(jì)算
calcSuffix: function() {
this.result = [];
for (var i = 0; i < this.suffix.length; i++) {
// 數(shù)值,直接壓入結(jié)果集
if (!this.isOp(this.suffix[i])) {
this.result.push(this.suffix[i]);
}
// 運(yùn)算符,從結(jié)果集中取出兩項(xiàng)進(jìn)行運(yùn)算,并將運(yùn)算結(jié)果置入結(jié)果集合
else {
this.result.push(this.opCalc(this.result.pop(), this.suffix[i], this.result.pop()));
}
}
// 此時(shí)結(jié)果集中只有一個(gè)值,即為結(jié)果
return this.result[0];
}
};
new Calculator('.calc-wrap');
});
以上就是本文的全部內(nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
- 簡易js代碼實(shí)現(xiàn)計(jì)算器操作
- js實(shí)現(xiàn)一個(gè)簡易計(jì)算器
- JavaScript實(shí)現(xiàn)一個(gè)簡易的計(jì)算器實(shí)例代碼
- javascript實(shí)現(xiàn)簡易計(jì)算器的代碼
- js制作簡易計(jì)算器
- JavaScript實(shí)現(xiàn)簡易加法計(jì)算器
- 超級(jí)簡易的JS計(jì)算器實(shí)例講解(實(shí)現(xiàn)加減乘除)
- js實(shí)現(xiàn)簡易計(jì)算器功能
- js實(shí)現(xiàn)一個(gè)簡易的計(jì)算器
- 用JavaScript做一個(gè)簡易計(jì)算器的三種方法舉例
相關(guān)文章
javascript的解析執(zhí)行順序在各個(gè)瀏覽器中的不同
javascript是一種解釋型語言,它的執(zhí)行是自上而下的。由于各個(gè)瀏覽器對(duì)它的理解有所差異,所以我們有必要深入理解js的執(zhí)行順序2014-03-03
在mpvue框架中使用Vant WeappUI組件庫的注意事項(xiàng)【推進(jìn)】
這篇文章主要介紹了在mpvue框架中使用Vant WeappUI組件庫的注意事項(xiàng),本文給大家提到了引入組件庫的兩種方法,需要的朋友可以參考下2019-06-06
JS中如何實(shí)現(xiàn)Laravel的route函數(shù)詳解
這篇文章主要給大家介紹了JS中是如何實(shí)現(xiàn)Laravel的route函數(shù),文中通過示例代碼介紹的很詳細(xì),相信對(duì)大家具有一定的參考價(jià)值,有需要的朋友們下面來一起看看吧。2017-02-02
Axios設(shè)置token請(qǐng)求頭的三種方式
用戶登錄時(shí),后端會(huì)返回一個(gè)token,并且保存到瀏覽器的localstorage中,可以根據(jù)localstorage中的token判斷用戶是否登錄,所以當(dāng)發(fā)送請(qǐng)求時(shí),都要攜帶token給后端進(jìn)行判斷,本文給大家介紹了Axios設(shè)置token請(qǐng)求頭的三種方式,需要的朋友可以參考下2024-02-02
JS實(shí)現(xiàn)簡易留言板(節(jié)點(diǎn)操作)
這篇文章主要為大家詳細(xì)介紹了JS實(shí)現(xiàn)簡易留言板,節(jié)點(diǎn)進(jìn)行操作,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2020-03-03
淺談JavaScript的幾種繼承實(shí)現(xiàn)方式
本文主要介紹了淺談JavaScript的幾種繼承實(shí)現(xiàn)方式,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2023-04-04

