溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點(diǎn)擊 登錄注冊 即表示同意《億速云用戶服務(wù)條款》

使用原生javascript編寫一個(gè)計(jì)算器

發(fā)布時(shí)間:2021-02-22 15:22:01 來源:億速云 閱讀:198 作者:Leah 欄目:開發(fā)技術(shù)

使用原生javascript編寫一個(gè)計(jì)算器?相信很多沒有經(jīng)驗(yàn)的人對此束手無策,為此本文總結(jié)了問題出現(xiàn)的原因和解決方法,通過這篇文章希望你能解決這個(gè)問題。

Java是什么

Java是一門面向?qū)ο缶幊陶Z言,可以編寫桌面應(yīng)用程序、Web應(yīng)用程序、分布式系統(tǒng)和嵌入式系統(tǒng)應(yīng)用程序。

計(jì)算器包括顯示數(shù)字區(qū)域和按鍵區(qū)域兩大部分,先把計(jì)算器的這兩個(gè)區(qū)域的html元素編寫出來,如下所示:

<div class="calculator_wrap" id="calculator"><!--計(jì)算器外包元素-->
 <div class="show_num"><!--顯示數(shù)字區(qū)域-->
 <div class="num_save" id="numSave"></div><!--計(jì)算公式-->
 <div class="num_cur" id="numCur">0</div><!--計(jì)算結(jié)果-->
 <div class="show_m" id="showM">M</div><!--記憶存儲標(biāo)志-->
 </div>
 <div class="btn_wrap" id="btnWrap"><!--按鈕區(qū)域-->
 <div class="btn" data-key="MC">MC</div><!--記憶清零-->
 <div class="btn" data-key="MR">MR</div><!--記憶讀取-->
 <div class="btn" data-key="MS">MS</div><!--存儲記憶-->
 <div class="btn" data-key="MA">M+</div><!--記憶加-->
 <div class="btn" data-key="ML">M-</div><!--記憶減-->
 <div class="btn" data-key="BACK">←</div><!--退格-->
 <div class="btn" data-key="CE">CE</div><!--清除當(dāng)前-->
 <div class="btn" data-key="Clear">C</div><!--清除-->
 <div class="btn" data-key="Negate">±</div><!--正負(fù)轉(zhuǎn)換-->
 <div class="btn" data-key="Square">√ ̄</div><!--平方根-->
 <div class="btn" data-key="Num" data-value="7">7</div><!--7-->
 <div class="btn" data-key="Num" data-value="8">8</div><!--8-->
 <div class="btn" data-key="Num" data-value="9">9</div><!--9-->
 <div class="btn" data-key="Base" data-value="/">/</div><!--除-->
 <div class="btn" data-key="Percentage">%</div><!--百分號-->
 <div class="btn" data-key="Num" data-value="4">4</div><!--4-->
 <div class="btn" data-key="Num" data-value="5">5</div><!--5-->
 <div class="btn" data-key="Num" data-value="6">6</div><!--6-->
 <div class="btn" data-key="Base" data-value="*">*</div><!--乘-->
 <div class="btn" data-key="Reciprocal">1/x</div> <!--倒數(shù)-->
 <div class="btn" data-key="Num" data-value="1">1</div><!--1-->
 <div class="btn" data-key="Num" data-value="2">2</div><!--2-->
 <div class="btn" data-key="Num" data-value="3">3</div><!--3-->
 <div class="btn" data-key="Base" data-value="-">-</div><!--減-->
 <div class="btn equal" data-key="Equal">=</div><!--等于-->
 <div class="btn zero" data-key="Num" data-value="0">0</div><!--0-->
 <div class="btn" data-key="Point">.</div><!--小數(shù)點(diǎn)-->
 <div class="btn" data-key="Base" data-value="+">+</div><!--加-->
 </div>
</div>

讀者可以自己編寫一些樣式,設(shè)計(jì)一個(gè)自己喜歡的計(jì)算器效果。本實(shí)例的計(jì)算器效果如下圖所示:

使用原生javascript編寫一個(gè)計(jì)算器

樣式代碼:

.calculator_wrap{width:240px;height:360px;padding:10px;margin:30px auto;border:1px solid #8acceb;background:#d1f1ff;}
 .calculator_wrap .show_num{position:relative;padding:0 8px;height:60px;background:#fff;text-align:right;}
 .calculator_wrap .show_m{position: absolute;left:10px;bottom:3px;display:none;}
 .calculator_wrap .num_save{height:26px;line-height:26px;font-size:12px;white-space:nowrap;}
 .calculator_wrap .num_cur{font-size:28px;height:34px;line-height:34px;}
 .calculator_wrap .btn_wrap{font-size:0px;}
 .calculator_wrap .btn{display:inline-block;width:38px;height:38px;line-height:38px;text-align:center;border:1px solid #ccc;background:#666;color:#fff;font-size:14px;margin:10px 10px 0 0;cursor:pointer;}
 .calculator_wrap .btn:hover{background:#333;}
 .calculator_wrap .btn:nth-child(5n){margin-right:0px;}
 .calculator_wrap .equal{position:absolute;height:90px;line-height:90px;}
 .calculator_wrap .zero{width:90px;}

對于新手來說,計(jì)算器功能看起來好像很復(fù)雜,那么多按鈕、多種計(jì)算方式,不知如何開始。其實(shí)任何一個(gè)功能,只需要理清楚思路,一步一步編寫代碼,會發(fā)現(xiàn)實(shí)現(xiàn)起來都不難。

1 獲取各個(gè)html元素

web前端不論要在頁面上做什么,都要先獲取頁面上的各個(gè)DOM元素。看起來整個(gè)計(jì)算器的按鈕較多,實(shí)際開發(fā)中可以使用事件代理來操作按鈕,所以只獲取所有按鈕的容器元素即可。代碼如下:

//獲取外包元素
var eCalculator = document.getElementById('calculator');
//保存運(yùn)算數(shù)據(jù)(公式)容器
var eNumSave = document.getElementById('numSave');
//當(dāng)前數(shù)字容器
var eNumCur = document.getElementById('numCur');
//按鈕外部容器,用于事件代理
var eBtnWrap = document.getElementById('btnWrap');
//記憶存儲標(biāo)志元素
var eShowM = document.getElementById('showM');

2 聲明相關(guān)變量

在運(yùn)算過程中,需要一些變量來進(jìn)行輔助計(jì)算、存儲結(jié)果和判斷等,如下所示:

//運(yùn)算公式
var sStep = '';
//當(dāng)前數(shù)字
var sCurValue = '0';
//運(yùn)算結(jié)果
var nResult = null;
//運(yùn)算符
var sMark = '';
//MR記憶存儲數(shù)據(jù)
var nMvalue = 0;
//輸入狀態(tài)。false:輸入數(shù)字替換原數(shù)字;true:輸入數(shù)字加到原數(shù)字后面;
var bLogStatus = false;

3 按鍵上添加點(diǎn)擊事件

因?yàn)檎麄€(gè)計(jì)算器按鍵較多,每一個(gè)按鈕都單獨(dú)綁定一個(gè)事件會顯得太多,很繁瑣,還會影響性能,且容易出錯(cuò)。所以剛才只獲取了按鍵的外部容器 eCalculator。

再使用事件代理,就只需要在容器上添加點(diǎn)擊事件,判斷當(dāng)前點(diǎn)擊的按鍵是哪一個(gè),再執(zhí)行對應(yīng)的計(jì)算即可。用鼠標(biāo)點(diǎn)擊按鍵的時(shí)候,可能會因?yàn)辄c(diǎn)得太快而選擇了按鍵上的文字,因此還需要在外包容器上添加一個(gè)阻止默認(rèn)行為的操作,代碼如下所示:

//外包容器添加鼠標(biāo)按下事件,用于防止選中文字
eCalculator.addEventListener('mousedown',function(event){
 //阻止鼠標(biāo)按下時(shí)的默認(rèn)行為,防止點(diǎn)擊按鈕過快時(shí)選中文字
 event.preventDefault();
});

//按鍵容器添加點(diǎn)擊事件,用于代理所有按鍵的操作
eBtnWrap.addEventListener('click',function(event){

});

3.1 獲取點(diǎn)擊的按鍵和值

通過事件函數(shù)傳入的event參數(shù),可以獲取到鼠標(biāo)點(diǎn)擊的元素。再通過元素上的data-key和data-value屬性判斷鼠標(biāo)點(diǎn)擊的是哪一個(gè)按鍵以及它的值,如下所示:

eBtnWrap.addEventListener('click',function(event){
 //獲取點(diǎn)擊的元素
 var eTarget = event.target;
 //判斷按下的鍵
 var key = eTarget.dataset.key;
 //獲取按下的值
 var value = eTarget.dataset.value;
});

3.2 判斷按鍵及值,數(shù)字鍵和小數(shù)點(diǎn)執(zhí)行輸入操作

如果按鍵屬性data-key是'Num'表示按下的是數(shù)字,'Point'表示小數(shù)點(diǎn)。

這些按鍵都是執(zhí)行輸入,因?yàn)閿?shù)字有多個(gè),所以把數(shù)字輸入封裝到fnInputNum函數(shù)中。再封裝fnShowResult函數(shù)把數(shù)據(jù)顯示到顯示數(shù)字區(qū)域。如下所示:

eBtnWrap.addEventListener('click',function(event){
 /* … */

 //判斷點(diǎn)擊的是否是按鍵
 if(key){
 //用switch語句判斷不同的按鍵執(zhí)行對應(yīng)的操作
 switch(key){
  //數(shù)字鍵執(zhí)行操作
  case 'Num':
  fnInputNum(value);
  break;
  //小數(shù)點(diǎn)操作
  case 'Point':
  //判斷是否有已小數(shù)點(diǎn),用于限制只能輸入一個(gè)小數(shù)點(diǎn)
  if(sCurValue.indexOf('.')==-1){
   sCurValue = sCurValue + '.';
   bLogStatus = true;
  }
  break;
 }
 //顯示數(shù)據(jù)到顯示數(shù)字區(qū)域
 fnShowResult();
 }
});
//輸入數(shù)字
function fnInputNum(num){
 //根據(jù)輸入狀態(tài)判斷是替換當(dāng)前數(shù)字還是添加到當(dāng)前數(shù)字后面
 if(bLogStatus){
 sCurValue = sCurValue + num;
 }else{
 //限制第一個(gè)數(shù)字不能是0
 if(num!=0){
  bLogStatus = true;
 }
 sCurValue = num;
 }
}
//顯示計(jì)算結(jié)果
function fnShowResult(){
 //顯示計(jì)算公式
 eNumSave.innerHTML = sStep;
 //限制數(shù)字總長度
 if(sCurValue.length>14){
 sCurValue = sCurValue.slice(0,14);
 }
 //顯示當(dāng)前數(shù)字
 eNumCur.innerHTML = sCurValue;
}

這時(shí)候已經(jīng)可以點(diǎn)擊數(shù)字和小數(shù)點(diǎn),輸入到計(jì)算器顯示屏上,如圖所示:

使用原生javascript編寫一個(gè)計(jì)算器

3.3 加減乘除運(yùn)算

計(jì)算器最基本的就是加減乘除運(yùn)算。為了實(shí)現(xiàn)對數(shù)字進(jìn)行加減乘除并計(jì)算結(jié)果功能,封裝fnCountResult、fnBaseCount和fnEqual三個(gè)函數(shù)。

fnCountResult用于根據(jù)運(yùn)算符計(jì)算結(jié)果;

fnBaseCount修改計(jì)算公式或計(jì)算結(jié)果;

fnEqual用于按下=號時(shí)計(jì)算結(jié)果,并重置數(shù)據(jù)。如下所示:

eBtnWrap.addEventListener('click',function(event){
 /* … */

 //判斷點(diǎn)擊的是否是按鍵
 if(key){
 //用switch語句判斷不同的按鍵執(zhí)行對應(yīng)的操作
 switch(key){
  /* … */
  //加減乘除基本運(yùn)算
  case 'Base':
  fnBaseCount(value);
  break;
  //等于
  case 'Equal':
  fnEqual();
  break;
 }
 //顯示數(shù)據(jù)到顯示數(shù)字區(qū)域
 fnShowResult();
 }
});
//計(jì)算結(jié)果
function fnCountResult(){
 //判斷當(dāng)前運(yùn)算符并執(zhí)行運(yùn)算
 switch(sMark){
 case '+':
  nResult = nResult===null?+sCurValue:nResult + (+sCurValue);
  break;
 case '-':
  nResult = nResult===null?+sCurValue:nResult - sCurValue;
  break;
 case '*':
  nResult = nResult===null?+sCurValue:nResult * sCurValue;
  break;
 case '/':
  nResult = nResult===null?+sCurValue:nResult / sCurValue;
  break;
 default:
  nResult = +sCurValue;
 }
}
//加減乘除基礎(chǔ)運(yùn)算
function fnBaseCount(key){
 //如果是輸入狀態(tài),進(jìn)行運(yùn)算
 if(bLogStatus){ 
 //修改輸入狀態(tài)
 bLogStatus = false;
 //計(jì)算公式
 sStep = sStep + ' ' + sCurValue + ' ' + key;
 //計(jì)算結(jié)果
 fnCountResult();
 sCurValue = ''+nResult;
 }else{
 //如果公式為空,先加上原始數(shù)字
 if(sStep==''){ 
  sStep = sCurValue + ' ' + key;
 }else{ //如果已有公式,更改最后的運(yùn)算符
  sStep = sStep.slice(0,sStep.length-1) + ' ' + key;
 }
 }
 //更改運(yùn)算符,用于計(jì)算
 sMark = key;
}
//等于
function fnEqual(){
 //如果沒有運(yùn)算符,阻止后續(xù)操作
 if(sMark=='')return;
 //計(jì)算結(jié)果
 fnCountResult();
 sCurValue = ''+nResult;
 //重置數(shù)據(jù)
 sStep = '';
 sMark = '';
 bLogStatus = false;
}

現(xiàn)在已經(jīng)可以在計(jì)算器上做加減乘除的計(jì)算了,如圖所示:

使用原生javascript編寫一個(gè)計(jì)算器

3.4 再給其他按鍵添加操作,代碼如下所示:

eBtnWrap.addEventListener('click',function(event){
 /* … */

 //判斷點(diǎn)擊的是否是按鍵
 if(key){
 //用switch語句判斷不同的按鍵執(zhí)行對應(yīng)的操作
 switch(key){
  /* … */

  //清除
  case 'Clear':
  fnClear()
  break;
  //退格
  case 'BACK':
  fnBack();
  break;
  //CE
  case 'CE':
  //清空當(dāng)前顯示數(shù)值
  sCurValue = '0';
  bLogStatus = false;
  break;
  //取反
  case 'Negate':
  //當(dāng)前數(shù)值取反
  sCurValue = ''+(-sCurValue);
  break;
  //取平方根
  case 'Square':
  //當(dāng)前數(shù)值取平方根
  nResult = Math.sqrt(+sCurValue);
  //其他數(shù)據(jù)初始化
  sCurValue = ''+nResult;
  sStep = '';
  sMark = '';
  bLogStatus = false;
  break;
  //倒數(shù)
  case 'Reciprocal':
  //當(dāng)前數(shù)值取倒數(shù)
  //其他數(shù)據(jù)初始化
  nResult = 1/sCurValue;
  sCurValue = ''+nResult;
  sStep = '';
  sMark = '';
  bLogStatus = false;
  break;
  //M系列
  case 'MC':
  //記憶數(shù)值清零
  nMvalue = 0;
  fnShowM()
  break;
  case 'MR':
  //顯示記憶數(shù)值
  sCurValue = '' + nMvalue;
  fnShowM()
  break;
  case 'MS':
  //記憶數(shù)值改為當(dāng)前數(shù)值
  nMvalue = +sCurValue;
  fnShowM()
  break;
  case 'MA':
  //當(dāng)前數(shù)值加到記憶數(shù)值中
  nMvalue += +sCurValue;
  fnShowM()
  break;
  case 'ML':
  //從記憶數(shù)值中減去當(dāng)前數(shù)值
  nMvalue -= +sCurValue;
  fnShowM()
  break;
 }
 //顯示數(shù)據(jù)到顯示數(shù)字區(qū)域
 fnShowResult();
 }
});
//清除
function fnClear(){
 //初始化所有數(shù)據(jù)
 sStep = '';
 sCurValue = '0';
 nResult = null;
 sMark = '';
 bLogStatus = false;
}
//退格
function fnBack(){
 //必須是輸入狀態(tài)才可以退格
 if(bLogStatus){
 //減去數(shù)值最后一位數(shù)
 sCurValue = sCurValue.slice(0,sCurValue.length-1);
 //如果最后數(shù)值為空或負(fù)號(-),改為0,重置輸入狀態(tài)為false,不可再退格
 if(sCurValue==''||sCurValue=='-'){
  sCurValue = '0';
  bLogStatus = false;
 }
 }
}
//判斷是否有M記憶存儲
function fnShowM(){
 bLogStatus = false;
 //判斷是否顯示記憶存儲標(biāo)志
 eShowM.style.display = nMvalue==0?'none':'block';
}

4 綁定鍵盤事件

寫到這里,計(jì)算器已經(jīng)可以正常使用了。不過只能用鼠標(biāo)點(diǎn)擊按鍵操作效率不高,為了可以更快的使用計(jì)算器,還需要加上鍵盤事件,當(dāng)按下對應(yīng)按鍵時(shí),執(zhí)行操作,如下所示:

//鍵盤事件
document.addEventListener('keyup',function(event){
 //獲取當(dāng)前鍵盤按鍵
 var key = event.key;
 //獲取按鍵code
 var code = event.keyCode;
 //限制正確的按鍵才修改顯示的數(shù)據(jù)
 var comply = false;
 //輸入數(shù)字
 if((code>=48&&code<=57)||(code>=96&&code<=105)){
 fnInputNum(key);
 comply = true;
 }
 //加減乘除
 if( key=='*'||key=='+'||key=='/'||key=='-'){
 fnBaseCount(key);
 comply = true;
 }
 //esc鍵
 if(code==27){
 fnClear();
 comply = true;
 }
 //回車鍵
 if(code==13){
 fnEqual();
 comply = true;
 }
 //退格鍵
 if(code==8){
 fnBack();
 comply = true;
 }
 if(comply){
 //顯示數(shù)據(jù)到計(jì)算器屏幕
 fnShowResult();
 }
});

看完上述內(nèi)容,你們掌握使用原生javascript編寫一個(gè)計(jì)算器的方法了嗎?如果還想學(xué)到更多技能或想了解更多相關(guān)內(nèi)容,歡迎關(guān)注億速云行業(yè)資訊頻道,感謝各位的閱讀!

向AI問一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI