JS基于递归实现网页版计算器的方法分析


Posted in Javascript onDecember 20, 2017

本文实例讲述了JS基于递归实现网页版计算器的方法。分享给大家供大家参考,具体如下:

递归实现网页版计算器可以简化代码,设计思路:

1、css+html实现计算器的外观,给每个button绑定number(z)事件,传入z的不同来区分触发事件的按钮。

<style>放入head中

这个div放在body中,是计算器的html,number()通过传入不同的数字,区分触发按钮。

<div class="bg">
 <div id="txt"></div>
 <button id="bt10" value="+">+</button>
 <button id="bt11" value="-">-</button>
 <button id="bt12" value="*">*</button>
 <br data-filtered="filtered"><button id="bt13" value="/">/</button>
 <button id="bt14" value="=">=</button>
 <br data-filtered="filtered"><button id="bt1" value="1">1</button>
 <button id="bt2" value="2">2</button>
 <button id="bt3" value="3">3</button>
 <br data-filtered="filtered"><button id="bt4" value="4">4</button>
 <button id="bt5" value="5">5</button>
 <button id="bt6" value="6">6</button>
 <br data-filtered="filtered"><button id="bt7" value="7">7</button>
 <button id="bt8" value="8">8</button>
 <button id="bt9" value="9">9</button> 
</div>

2、在number(z)方法中,利用DOM的innerHTML实现表达式的实时显示,并用字符串content存储已点击的数字或符号,当点击"="时,调用fact(content)进行计算。

代码如下:

var content; //存储已点击的数字或符号,要定义成全局的,如果定义在number()中,每次content都会被重新赋值
function number(z) {
  var k=document.getElementById("txt");//获取显示框的 DOM,并缓存在k中
  if(z==14){//如果点击了"="号
   var sum = fact(content);//调用fact()进行计算,并把结果赋值给sum
   content=content+"="+sum;//在要显示的内容后加入"="和sum
   k.innerHTML = content;
   content = null;//将content清空,准备下次计算
  }else{
  //如果没有点击"="号,而是点击的运算符,就需要通过switch把数字转化成运算符
   switch(z){
    case 10: z = '+'; break;
    case 11: z = '-'; break;
    case 12: z = '*'; break;
    case 13: z = '/'; break;
   }
   //把此时输入的字符存入content
   if(content){
    content+=z.toString();
   }else{
    content=z.toString();
   }
   k.innerHTML = content;//让它实时显示
  }
}

3、本计算器中递归算法的思路:fact(content)中,先用content.indexOf("+")判断"+"号是否存在,若存在,则分别递归调用index前后的两个字符串,并让其相加,直到所有串中都找不到"+"后,开始用content.lastIndexOf("-")判断"-"号,后续操作和加号一样,存在则递归index前后的两个字符串,并让其相减,直到找不到减号,就开始判断乘号和除号,直到没有符号后返回parseFloat(content),这里的content是递归调用后的无符号字符串,并不是最开始引入的参数了。

//实现递归计算
function fact(content){
 var index = content.indexOf("+");//获取"+"号的index
 if(index != -1){
  return fact(content.substring(0,index))+fact(content.substring(index+1));
  //当找得到“+”号时,分成两部分相加递归
 }else{
  var index2 = content.lastIndexOf("-");//当找不到“+”号时,开始找“-”号
  if(index2 != -1){
   return fact(content.substring(0,index2))-fact(content.substring(index2+1));
   //当找得到“-”号时,分成两部分相减递归
  }else{
   var index3 = content.indexOf("*");//当找不到“-”号时,开始找“*”号
   if(index3 != -1){
    return fact(content.substring(0,index3))*fact(content.substring(index3+1));
    //当找得到“*”号时,分成两部分相乘递归
   }else{
    var index4 = content.lastIndexOf("/");//当找不到“*”号时,开始找“/”号
    if(index4 != -1){
     return fact(content.substring(0,index4))/fact(content.substring(index4+1));
     //当找得到“/”号时,分成两部分相除递归
    }else{
     return parseFloat(content);//当找不到“/”号时,返回这段串的变成float型的数值
    }
   }
  }
 }
}

以上是全部代码,设计思路中要注意的两点是:

1、加号和乘号用的indexOf(),而减号和除号用的lastIndexOf()

举个例子:content="3-2-1"

它如果用indexOf(),先把串分成fact("3")-fact("2-1"),前面"3"无符号,递归调用fact时返回parseFloat("3"),而后面的递归调用时,会变成parseFloat("2")-parseFloat("1")=1,这个是fact("2-1")的返回值,最终结果是2,这就相当于:3-(2-1)。

如果用lastIndexOf(),它把串分成fact("3-2")-fact("1")fact("3-2")的返回值是parseFloat("3")-parseFloat("2")=1,这样就实现了从左到右的计算。

除号也是同理:若content="6/3/2"用indexOf(),相当于:6/(3/2),因为加号和乘号不存在顺序问题,因此可以用indexOf()。

2、乘除在判断的内层,加减在判断的外层。

由于乘除要先计算,内层的判断会先获得没有符号的串,他们就会先计算。

这个计算器个人觉得可以优化的地方:(大家也可以思考下)

1、给button绑定事件的时候,采用事件代理模式。
2、用到的哪些属性或方法需要考虑浏览器兼容问题。

本人最开始做的是非递归的两个数加减乘除的计算器,后面改进的时候,想做多个数的计算,思考起来就更复杂了。当采用递归来写,代码量比之前小,易阅读,并且思考起来不复杂。感兴趣的可以试一试。

PS:这里再为大家推荐几款计算工具供大家进一步参考借鉴:

在线一元函数(方程)求解计算工具:
http://tools.3water.com/jisuanqi/equ_jisuanqi

科学计算器在线使用_高级计算器在线计算:
http://tools.3water.com/jisuanqi/jsqkexue

在线计算器_标准计算器:
http://tools.3water.com/jisuanqi/jsq

希望本文所述对大家JavaScript程序设计有所帮助。

Javascript 相关文章推荐
身份证号码前六位所代表的省,市,区, 以及地区编码下载
Apr 12 Javascript
使用Jquery Aajx访问WCF服务(GET、POST、PUT、DELETE)
Mar 16 Javascript
基于jQuery的图片左右无缝滚动插件
May 23 Javascript
使图片旋转的3种解决方案
Nov 21 Javascript
JavaScript获取鼠标移动时的坐标(兼容IE8、chome谷歌、Firefox)
Sep 13 Javascript
调试JavaScript中正则表达式中遇到的问题
Jan 27 Javascript
javascript去掉代码里面的注释
Jul 24 Javascript
jquery获取复选框checkbox的值实现方法
May 30 Javascript
浅谈jquery中的each方法$.each、this.each、$.fn.each
Jun 23 Javascript
灵活使用数组制作图片切换js实现
Jul 28 Javascript
微信小程序实现动态设置placeholder提示文字及按钮选中/取消状态的方法
Dec 14 Javascript
详解如何在vue项目中使用eslint+prettier格式化代码
Nov 10 Javascript
JS小球抛物线轨迹运动的两种实现方法详解
Dec 20 #Javascript
JavaScript实现二叉树定义、遍历及查找的方法详解
Dec 20 #Javascript
axios中cookie跨域及相关配置示例详解
Dec 20 #Javascript
JavaScript实现重力下落与弹性效果的方法分析
Dec 20 #Javascript
axios进阶实践之利用最优雅的方式写ajax请求
Dec 20 #Javascript
vue.js $refs和$emit 父子组件交互的方法
Dec 20 #Javascript
jQuery进阶实践之利用最优雅的方式如何写ajax请求
Dec 20 #jQuery
You might like
IStream与TStream之间的相互转换
2008/08/01 PHP
PHP删除特定数组内容并且重建数组索引的方法.
2011/03/25 PHP
PHP那些琐碎的知识点(整理)
2017/05/20 PHP
JavaScript 设计模式 安全沙箱模式
2010/09/24 Javascript
js 函数的副作用分析
2011/08/23 Javascript
用函数模板,写一个简单高效的 JSON 查询器的方法介绍
2013/04/17 Javascript
javascript通过className来获取元素的简单示例代码
2014/01/10 Javascript
jquery中交替点击事件的实现代码
2014/02/14 Javascript
使用jQuery实现的掷色子游戏动画效果
2014/03/14 Javascript
js字符串完全替换函数分享
2014/12/03 Javascript
JS简单实现动画弹出层效果
2015/05/05 Javascript
基于javascript制作经典传统的拼图游戏
2016/03/22 Javascript
JS实现鼠标滑过显示边框的菜单效果
2016/09/21 Javascript
KnockoutJS 3.X API 第四章之数据控制流component绑定
2016/10/10 Javascript
js 原型对象和原型链理解
2017/02/09 Javascript
jquery仿京东侧边栏导航效果
2017/03/02 Javascript
Angular.js中下拉框实现渲染html的方法
2017/06/18 Javascript
js实现拖拽上传图片功能
2017/08/01 Javascript
vue router 配置路由的方法
2018/07/26 Javascript
浅谈vuex为什么不建议在action中修改state
2020/02/02 Javascript
vue实现一个矩形标记区域(rectangle marker)的方法
2020/10/28 Javascript
python实现从字典中删除元素的方法
2015/05/04 Python
启动targetcli时遇到错误解决办法
2017/10/26 Python
python多线程并发及测试框架案例
2019/10/15 Python
python实现图像拼接功能
2020/03/23 Python
CSS3实现菜单悬停效果
2020/11/17 HTML / CSS
Sofft鞋官网:世界知名鞋类品牌
2017/03/28 全球购物
手机配件第一品牌:ZAGG
2017/05/28 全球购物
宝拉珍选官方旗舰店:2%水杨酸精华液,收缩毛孔粗大和祛痘
2018/07/01 全球购物
尼克松手表官网:Nixon手表
2019/03/17 全球购物
财务管理专业推荐信
2013/11/19 职场文书
小学生暑假家长评语
2014/04/17 职场文书
2014组织生活会方案
2014/05/19 职场文书
有限责任公司股东合作协议书范本
2014/10/30 职场文书
小学六年级班主任工作经验交流材料
2015/11/02 职场文书
银行求职信范文
2019/05/13 职场文书