您的位置:首页 > Web前端 > JavaScript

[教程]JS从糊涂到明白:一步一步编写计算器2 – 简化代码

2010-07-16 02:11 901 查看
[文章原始发表:This Is WWW : http://www.plrsoft.cn/blog/?p=69 转载请注明出处]
我在上一篇文章“一步一步编写计算器 – 构建和兼容”中在做好第一个简易计算器的时候曾说道:事实上,我们可以做得更加精简,20行代码之内就可以搞定。大家可能觉得很奇怪,你光是JAVASCRIPT就已经达到14行了呀,还有6行,你怎么写得出那10几个显示屏和按键的控件来?

我要告诉你,完全没问题!

大家先观察这个代码:

<!--content start-->
<div id="calc">
<!--这里是显示屏 start-->
<div id="screen"><input id="result" readonly="readonly" type="text" value="0" /></div>
<!--这里是显示屏 end-->
<!--这里是功能键 start-->
<div id="button">
<input id="num_1" onclick="javascript:add_num(this.value)" type="button" value="1" accesskey="A" />
<input id="num_2" onclick="javascript:add_num(this.value)" type="button" value="2" />
<input id="num_3" onclick="javascript:add_num(this.value)" type="button" value="3" />
<input id="num_4" onclick="javascript:add_num(this.value)" type="button" value="4" />
<input id="num_5" onclick="javascript:add_num(this.value)" type="button" value="5" />
<input id="num_6" onclick="javascript:add_num(this.value)" type="button" value="6" />
<input id="num_7" onclick="javascript:add_num(this.value)" type="button" value="7" />
<input id="num_8" onclick="javascript:add_num(this.value)" type="button" value="8" />
<input id="num_9" onclick="javascript:add_num(this.value)" type="button" value="9" />
<input id="num_0" onclick="javascript:add_num(this.value)" type="button" value="0" />
<input id="btn_plus" onclick="javascript:add_btn(this.value)" type="button" value="+" />
<input id="btn_cut" onclick="javascript:add_btn(this.value)" type="button" value="-" />
<input id="btn_multi" onclick="javascript:add_btn(this.value)" type="button" value="×" />
<input id="btn_divid" onclick="javascript:add_btn(this.value)" type="button" value="÷" />
<input id="btn_divid" onclick="javascript:add_btn(this.value)" type="button" value="." />
<input id="btn_ce" onclick="javascript:add_btn(this.value)" type="button" value="CE" />
<input id="=" onclick="javascript:get_result()" type="button" value="=" /></div>
<!--这里是功能键 end-->
</div>

发现没有?其实,这里面很多代码都是重复的! 仔细观察这俩行!

...
<input id="num_0" onclick="javascript:add_num(this.value)" type="button" value="0" />
<input id="btn_plus" onclick="javascript:add_btn(this.value)" type="button" value="+" />  ...

请告诉我他们的区别! 是的,他们的区别仅在于value属性、id属性以及ONCLICK的动作不同!那就好办了!干重复的活儿是计算机的强项,而人比计算机更强的功能就是,能灵活的让一件重复的事情出现微妙的变化!

于是,我决定将所有的按键控件都用javascript生成,然后填充到id=button这个DIV中! 所以我们要准备一个初始化函数btn_init(),然后将这个函数放入的ONLOAD事件中代码如下;

<div id="main_div">
<!--content start-->
<div id="calc">
<!--这里是显示屏 start-->
<div id="screen"><input id="result" readonly="readonly" type="text" value="0" /></div>
<!--这里是显示屏 end-->
<!--这里是功能键 start-->
<div id="button"></div>
<!--这里是功能键 end-->
</div>
<!--content end-->
</div>


/*---动态构建按钮控件  start---*/
function btn_init()
{
btn_list=new Array(1,2,3,4,5,6,7,8,9,0,"+","-","×","÷",".","CE","=");  //设置一个数组,存储按键
var button_area =   document.getElementById("button");    //这里就是要写入控件的地方

for(var i=0;i<btn_list.length;i++)
{

//控件的生成,分为两种,一种是数字,一种是非数字,分别绑定不同的动作
if(isNaN(btn_list[i])) //如果不是数字,则绑定add_btn()事件 否则绑定add_num()
{
//进行一个特殊功能的处理:=
if(btn_list[i]=="="){
button_area.innerHTML+="<input type='button' value='=' id='=' onclick='javascript:get_result()'/>";
}else{
button_area.innerHTML+=" <input type=\"button\" value=\""+btn_list[i]+"\" id=\"btn_"+btn_list[i]+"\" onclick=\"javascript:add_btn(this.value)\"/>";
}
}else{
button_area.innerHTML+=" <input type=\"button\" value=\""+btn_list[i]+"\" id=\"btn_"+btn_list[i]+"\" onclick=\"javascript:add_num(this.value)\"/>";
}
}
}
/*---动态构建按钮控件  end---*/

OK,现在我们的代码生成了!

点这里运行一下! 看,他跑起来了!

是的,它跑起来了!但是,还远远达不到我们的目标!20行代码!怎么实现?继续观察,我们发现,很多行代码主要花在了判断上,那么我们能不能将一些功能合并呢?比方说,不管按键是数字还是非数字,一律使用“add_btn()”,抛弃掉add_num()和get_result()函数,这样,我们在生成控件环节可以节省很多的代码。同时,将add_btn()、add_num()、get_result()三个函数合并,也能缩减代码数量,也能抛弃掉判断特殊功能的代码(比如要多一个判断语句判断“=”以便分配特殊动作)!

说干就干,我们先缩短代码生成函数

/*---动态构建按钮控件  start---*/
function btn_init()
{
btn_list=new Array(1,2,3,4,5,6,7,8,9,0,"+","-","×","÷",".","CE","=");  //设置一个数组,存储按键
var button_area =   document.getElementById("button");    //这里就是要写入控件的地方
for(var i=0;i<btn_list.length;i++)
{
button_area.innerHTML+=" <input type=\"button\" value=\""+btn_list[i]+"\" id=\"btn_"+btn_list[i]+"\" onclick=\"javascript:add_btn(this.value)\"/>";
}
}
/*---动态构建按钮控件  end---*/

JUST 11行! 除掉注释,然后将for循环合并成一行,只剩下5行 ,这下清爽了吧!这里5行,加上先前构建最最最简单的计算器的功能实现代码14行,一共是19行!说20行还多呢!

再让我们来合并add_btn()、add_num()、get_result()三个函数,同时,我们也进一步的修正前面还存在的一些小BUG,比如,归零后,输入的第一个数字前老会带一个0的囧况!代码如下:

is_res=false;    //设定全局变量 is_res
function add_btn(act){    //向显示屏添加运算符号
if(is_res==true)
{
result.value="0";    //显示屏归零
is_res=false;       //将IS_RES变量标记为键盘输入状态,表示当前显示屏的数字是输入的,而非运算结果
}
if (act=="CE"){result.value="0";}
else if (act=="="){
/*这里增加对=的特殊处理  亦即合并get_result()函数--*/
var res_temp=result.value;              //设置一个临时变量来进行运算符替换,以免将中间过程显示到屏幕上
res_temp=res_temp.replace(/[×]/g,"*");  //将所有的乘号换成*
res_temp=res_temp.replace(/[÷]/g,"/");  //将所有的除号换成/
result.value=eval(res_temp);
is_res=true;                            //将IS_RES变量标记为结果状态,标示当前显示屏的数字是运算结果,而非输入状态。
/*---合并结束--*/
}
else if(isNaN(act)==false)
{
if(result.value==0){result.value="";}
result.value+=act
}     //合并 add_num(),将数字原本的显示在屏幕上
else {

/*----设置一个临时变量来进行正则替换,以免将中间过程显示到屏幕上--*/
var result_temp =result.value+act;
var temp_parr = "";

/*---------------寻找整个运算式第一个数字为0且其后所跟的符号不是运算符和小数点的数字---------------*/
var parr1=/(^0+)([0-9])/;
if(parr1.test(result_temp))
{   //设定替换语句,将整个运算式第一个数字为0开头的数字去除
temp_parr = result_temp.match(parr1)[2];
result_temp=result_temp.replace(parr1,temp_parr);
}

/*---------------寻找整个运算式第一个数字为负号 - 的数字---------------*/
var parr2=/(^-*)(0*)(.*)/;
if(parr2.test(result_temp))
{             //将非负号的符号去除
temp_parr = result_temp.match(parr2)[1]+result_temp.match(parr2)[3];
result_temp=result_temp.replace(parr1,temp_parr);
}

/*---------------将当前运算式中除运算符号外的所有数字取出---------------*/
var parr3=/(?=[+-×÷]){1}([0-9.]+)(?=[+-×÷]){1}/g;
if(parr3.test(result_temp))
{
temp_parr = result_temp.match(parr3);    //用match方法取出当前式子中的数字
for(var i=0;i<temp_parr.length;i++)
{
var nozero_parr=Number(temp_parr[i]);       //让每一个数字都成为一个合法数值
result_temp=result_temp.replace(temp_parr[i],nozero_parr);
}
}

/*---------------寻找算式中连续出现的运算符号,诸如++,x-+等---------------*/
var parr4=/[^0-9]{2,}/g;

if(parr4.test(result_temp))
{
temp_parr = result_temp.match(parr4);
for(var i=0;i<temp_parr.length;i++)
{
var cur_sign = new Array(temp_parr[i].substring(0,1),temp_parr[i].substring(1,2));  //取出符号串的前两个符号            //创建一个数组,将取出来的符号串的第一个符号和第二个符号存入一个数组
var temp_sign="";
if(cur_sign[1]=="-")
{
temp_sign=cur_sign[0]+cur_sign[1];
}else{
temp_sign=cur_sign[0];
}  //如果第二个符号不是负号,那么只保留第一个符号,否则就保留两个符号
result_temp=result_temp.replace(temp_parr[i],temp_sign);
}
}

result.value=result_temp;

}
}

OK,这样,我们就将代码简化完成了!

查看运行效果

很完美!我们在简化的同时,还做了一些工作,那就是为程序的以后扩展做出了铺垫。

一个程序的可扩展性和可方便扩展性是很重要的,比方说,以后如果你要给这个计算器加入开方、乘方、计算正弦余弦的功能,总不能超级麻烦的先在页面添加 input 控件,然后指定一个动作,再去修改JAVASCRIPT吧,那样的代码,只会越来越庞杂。所以,再最开始构建程序的时候,就要考虑到以后如何可以很方便的直接修改JS代码就可以,要基本上做到代码跟页面架构相分离,这种分离有利于页面表现和页面内容的维护。

下一节,将会讲到如何进行功能扩展。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息