[文章原始发表:This Is WWW : http://www.plrsoft.cn/blog/?p=69  转载请注明出处]
 
    JAVASCRIPT有那么难么?NO!智商不是最重要的,最关键的是——练习!更多的练习!
    古人都说,写代码要形成自己的风格,其实说白了,就那么大一块地方,也就那么几个关键字,要形成自己的风格,只要做到两个字——不乱。
    本文适合有一定HTML和javascript基础的同学们观看,我将从制作一个计算器开始,一步一步让你了解JAVASCRIPT的构建、容错、代码逐步求精。
 
    好的,我们就从制作一个最最最简单的计算器开始!
    第一步:编写基本的HTML和JS代码,实现基本功能。
 
   
<div id="calc">
<!--这里是显示屏 start-->
                        <div id="screen">
                             <input id="result" readonly="readonly" type="text" />
                     </div>
<!--这里是显示屏 end-->    
    
<!--这里是功能键 start-->
<div id="button">
    <input id="num_1" onclick="javascript:add_num(this.value)" type="button" value="1" />
    <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_ce" onclick="javascript:add_btn(this.value)" type="button" value="CE" />
    <input id="=" onclick="javascript:get_result()" type="button" value="=" />
</div>
<!--这里是功能键 end-->
</div>
 
  然后为按键添加动作,向显示屏添加数字的add_num()函数、为数字添加运算符的add_btn()函数、获取结果的get_result()函数;
 
    
function add_num(num)
{    
    result.value+=num;        //向显示屏添加数字 result.value+=num    是 result.value=result.value+num 的简写    
}    
function add_btn(act)
{        //向显示屏添加运算符号    
    if (act=="CE"){result.value="";}        
    else {result.value+=act;}    
}    
function get_result()
{    
    result.value=eval(result.value);    //通过eval函数对屏幕上的运算串进行运算并输出结果
}
 
   OK,40行代码(事实上,我们可以做得更加精简,20行代码之内就可以搞定。这一点留到下一节来讲),一个简易的计算器就诞生了,他还可以计算正负数哦! 大家可以点击这个链接查看运行效果..
 
   第二步:修改不爽的地方
  
   可能大家在使用中发现了,在这个小程序运行过程中,还存在以下几个BUG:
1、完成一次计算后,再次点击数字按钮,它居然会在原有的结果后添加数字,而非先清空屏幕,重新写入一个数字。
2、乘(*)和除(/)不符合人们的视觉习惯,还不能计算小数。
3、居然能够输入N个运算符号!比如,这种算式居然是可以合法计算出来的:9*-+-6=54!同时,我们还要避免新加入的“计算小数”功能出现多个小数点的情况
4、居然能输入0开头的数字!
5、居然不能键盘输入
 
现在我们来分析原因,找出解决办法:
 
    针对第一点,主要是由于程序没有判断到屏幕的数字到底是输入的,还是计算结果而导致的。所以解决办法就是为屏幕的数字设定一个标记,以告诉程序这些数字是按键输入的,还是计算结果。

    这个修改,我们只需要在向显示屏添加数字的函数add_num()、设置动作的函数add_btn()、获取结果的函数get_result()中添加一个标记即可。我们把这个标记命名为is_res,他是一个全局变量的布尔值,只有true和false两个值。当为false时,指定为“按键输入”,当为true时,指定为“eval的结果”,然后在add_num()和add_btn()函数中,对这个值进行判断,以做出是否清空显示屏的决定。代码如下:
 
 
function add_num(num)
{
        if(is_res==true)
        {
                result.value="0";        //显示屏归零
                is_res=false;             //将IS_RES变量标记为键盘输入状态,表示当前显示屏的数字是输入的,而非运算结果
        }
        result.value+=num;        //向显示屏添加数字 result.value+=num    是 result.value=result.value+num 的简写
}    
    
function add_btn(act)
{        //向显示屏添加运算符号
        if(is_res==true)
        {
                result.value="0";        //显示屏归零
                is_res=false;             //将IS_RES变量标记为键盘输入状态,表示当前显示屏的数字是输入的,而非运算结果
        }
        else if (act=="CE"){result.value="";}
        else    
        {
                result.value=result_temp;
        }
}
 
   针对第二点,需要将按键的VALUE更改为×和÷,然后在获取结果的get_result()函数中将×和÷恢复成*和/,以使得运算函数EVAL能够正常运行即可。加入小数点功能
 
 
<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="." />
 
function 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变量标记为结果状态,标示当前显示屏的数字是运算结果,而非输入状态。
}
 
    针对第三点,主要是程序没有判断输入的字符是否符合算式标准造成的,所以解决办法就是为每一次输入安装一个“过滤器”,过滤掉多余的运算符即可,这个兼容性改动,我们主要在为数字添加运算符的add_btn()函数中完成。
   第四点,同第二点的解决办法。
 
    在这里,我们要请出强大的正则工具来进行替换了,首先我们要搞清楚哪些情况是允许存在的:
1、诸如 A × -B A ÷ -B这个是可以存在的
2、诸如 A- ×B 、A × +-B 这种是要禁止的
3、诸如 A ÷ -+–+B 这种是要禁止的
 
   综合一下,那就是1、运算符号前面不能存在正负号 2、连续有多个运算符号时,应强制只保留第一个输入的符号
    所以我们在add_btn()函数中构建以下正则表达式来进行过滤,
function add_btn(act)
{        //向显示屏添加运算符号    
     if(is_res==true)    
     {    
         result.value="0";        //显示屏归零        
         is_res=false;             //将IS_RES变量标记为键盘输入状态,表示当前显示屏的数字是输入的,而非运算结果    
     }    
     else if (act=="CE"){result.value="0";}        
     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;    
    
        }    
}
    第五点,需要为页面的onkeydown动作增加一个新的函数,用来获取当前的按键值,然后调用相应的函数即可。这个问题是比较麻烦的,我们放到第三小节的“功能扩展”中一并解决。
    到这里为止,我们的全部代码经过修正,就像下面这个样子了:
 
<!--content start-->    
    
                        <div id="calc">    
                                <!--这里是显示屏 start-->    
                                <div id="screen">
                                        <input type="text" readonly="readonly" id="result" value="0">
                                </div>    
                                <!--这里是显示屏 end-->    
                                <!--这里是功能键 start-->                        
                                <div id="button">    
                                        <input type="button" value="1" id="num_1" accesskey="A" onclick="javascript:add_num(this.value)"/>    
                                        <input type="button" value="2" id="num_2" onclick="javascript:add_num(this.value)"/>    
                                        <input type="button" value="3" id="num_3" onclick="javascript:add_num(this.value)"/>    
                                        <input type="button" value="4" id="num_4" onclick="javascript:add_num(this.value)"/>    
                                        <input type="button" value="5" id="num_5" onclick="javascript:add_num(this.value)"/>    
                                        <input type="button" value="6" id="num_6" onclick="javascript:add_num(this.value)"/>    
                                        <input type="button" value="7" id="num_7" onclick="javascript:add_num(this.value)"/>    
                                        <input type="button" value="8" id="num_8" onclick="javascript:add_num(this.value)"/>    
                                        <input type="button" value="9" id="num_9" onclick="javascript:add_num(this.value)"/>    
                                        <input type="button" value="0" id="num_0" onclick="javascript:add_num(this.value)"/>    
                                        <input type="button" value="+" id="btn_plus" onclick="javascript:add_btn(this.value)"/>    
                                        <input type="button" value="-" id="btn_cut" onclick="javascript:add_btn(this.value)"/>    
                                        <input type="button" value="×" id="btn_multi" onclick="javascript:add_btn(this.value)"/>    
                                        <input type="button" value="÷" id="btn_divid" onclick="javascript:add_btn(this.value)"/>    
                                        <input type="button" value="." id="btn_divid" onclick="javascript:add_btn(this.value)"/>    
                                        <input type="button" value="CE" id="btn_ce" onclick="javascript:add_btn(this.value)"/>    
                                        <input type="button" value="=" id="=" onclick="javascript:get_result()"/>    
                                </div>    
                                <!--这里是功能键 end-->    
                        </div>
 
is_res=false;        //设定全局变量 is_res    
function add_num(num)
{    
                if(is_res==true)    
                {    
                        result.value="0";        //显示屏归零        
                        is_res=false;             //将IS_RES变量标记为键盘输入状态,表示当前显示屏的数字是输入的,而非运算结果    
                }    
                result.value+=num;        //向显示屏添加数字 result.value+=num    是 result.value=result.value+num 的简写    
}    
    
function add_btn(act)
{        //向显示屏添加运算符号    
                if(is_res==true)    
                {    
                        result.value="0";        //显示屏归零        
                        is_res=false;             //将IS_RES变量标记为键盘输入状态,表示当前显示屏的数字是输入的,而非运算结果    
                }    
                else if (act=="CE"){result.value="0";}        
                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;    
    
                        }    
}    
    
function 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变量标记为结果状态,标示当前显示屏的数字是运算结果,而非输入状态。    
}
 
 
    大家可以运行一下 查看运行效果
下一节讲给大家讲述如何将代码求精,即将其体积简化且方便后续新功能的扩展!