最近研究月影的《JavaScript王者归来》,会不间断的写一些读书笔记。
一、概要需求清单
1.支持鼠标点击按钮的操作方式
2.提供普通的四则运算功能
3.支持乘方开方、倒数、百分比功能
4.提供记忆功能
5.运算范围、精度达到要求
6.运算异常时返回异常状态和异常提示信息
7.提供清除并从异常恢复的功能
二、系统设计
1、系统用例图
2、界面原型
3、领域模型/功能设计
- 一个用来保存中间计算结果的对象,初始值为0
- 一个用来保存当前操作符的对象,初始值为0
- 一个操作符与运算函数的映射表
- 一个根据当前操作符来返回中间结果和当前数值运算结果的闭包
- 一个保存记忆结果的对象
用两个堆栈n和p来保存操作数a,b和操作函数o,需要计算的时候将a,b和o分别弹出并传入闭包d,计算d(a,b,o)的值,将该值传入堆栈n
算法描述如下:
n.push(a);
p.push(o);
n.push(b);
n.push(p.pop()(n.pop(),n.pop()));
p.push(o);
n.push(b);
......
操作符与运算函数的映射表(使用对象常量方式—obj={x:1;y:2},相当于obj.x=1,obj.y=2)
var opMap={ "+":function(a,b){return b+a}, //处理加法的闭包 "-":function(a,b){return b-a}, //处理减法的闭包 "*":function(a,b){return b*a}, //处理乘法的闭包 "/":function(a,b){return b/a}, //处理除法的闭包 "=":function(a,b){return a}, //处理最终结果 }
存储数值、操作符和输入缓存的数据结构
var oMemery = { numStack : [], //存储数值 operStack : [], //存储字符串 inBuffer : "" //输入显示缓存 }
三、核心算法
1.计算表达式的闭包
function doOper(){ with(oMemory){ if(operStack.length){ try { var op=opMap[operStack.pop()]; var args =[]; //取得栈顶运算符 for(var i=0;i<op.length;i++){ args.push(numStack.pop()); } //从数组堆栈中依次取相应的操作数进行处理 numStack.push(op.apply(this, args)); } catch(ex) { alert(ex.message); } } return numStack[numStack.length-1]; } }
2、两个外部接口分别用来接收数值和操作符