实现简易计算器

前言

通过JavaScript来实现一个简易的计算器,并一步步对代码进行优化。

实现效果页面展示

HTML结构

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
<body>
<p id="title">简 易 计 算 器</p>
<div id="calculator">
<p>
<input type="text" class="formerInput" value="null">
<span class="sign"> + </span>
<input type="text" class="laterInput" value="null">
<span> = </span>
<span class="resultOutput"> null </span>
</p>
<p>
<input type="button" value=" + " >
<input type="button" value=" - " >
<input type="button" value=" × " >
<input type="button" value=" ÷ " >
</p>
</div>
</body>

步骤:
1、用一个<div>包裹计算器的内容信息。
2、在<div>里设置两个<p>。上面为计算输出块,下面为选择运算符块。数字输入框用<input type=”text”>,计算符号和结果输出使用<span>,运算符使用<input class=”button”>进行选择。

CSS样式

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
<style type="text/css">
body{
background-color: #eee;
}
#title{
text-align: center;
font-size: 70px;
margin-top: 120px;
}
#calculator{
width: 420px;
height: 100px;
padding: 80px;
position: absolute;
left: 0;
right: 0;
top: 0;
bottom: 0;
margin: auto;
}
</style>

对<div>进行定位使之垂直居中,设置一些自定义样式。

JavaScript分析

最简易的方法

先在input-button上绑定点击事件进行调用,然后再获取到节点,编写绑定的事件函数。
缺点:方法虽然简单,但是结构与行为没有进行分离。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
<body>
<p id="title">简 易 计 算 器</p>
<div id="calculator">
<p>
<input type="text" class="formerInput" value="null">
<span class="sign"> + </span>
<input type="text" class="laterInput" value="null">
<span> = </span>
<span class="resultOutput"> null </span>
</p>
<p>
<input type="button" value=" + " onclick="add()" name="add">
<input type="button" value=" - " onclick="subtract()" name="suntract">
<input type="button" value=" × " onclick="multiply()" name="multiply">
<input type="button" value=" ÷ " onclick="divide()" name="divide">
</p>
</div>

<script type="text/javascript">
//最容易的方法
//获取元素
var calculator = document.querySelector('#calculator');
var formerInput = calculator.querySelector(".formerInput");
var laterInput = calculator.querySelector(".laterInput");
var sign= calculator.querySelector(".sign");
var resultOutput = calculator.querySelector(".resultOutput");
//add
function add(){
sign.innerHTML = ' + ';
//dom取到的值为字符串,字符串相加会变拼接,需要转换成数值
resultOutput.innerHTML = +formerInput.value + +laterInput.value;
}
//subtract
function subtract(){
sign.innerHTML = ' - ';
//不用转换,因为字符串不能相减
resultOutput.innerHTML = formerInput.value - laterInput.value
}
//multiply
function multiply(){
sign.innerHTML = ' × ';
resultOutput.innerHTML = formerInput.value * laterInput.value;
}
function divide(){
sign.innerHTML = ' ÷ ';
resultOutput.innerHTML =+formerInput.value / laterInput.value;
}

</script>

改进一(结构与行为的分离)

取消内嵌在<input>标签里的点击事件调用,把事件调用放到<script>里进行shi’j

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
<script type="text/javascript">
//获取元素
var calculator = document.querySelector('#calculator');
var formerInput = calculator.querySelector(".formerInput");
var laterInput = calculator.querySelector(".laterInput");
var sign= calculator.querySelector(".sign");
var resultOutput = calculator.querySelector(".resultOutput");
//获取所有class为btn的节点
var btns = calculator.querySelectorAll(".btn");

//通过类数组下标绑定事件,传的是函数名,而不是函数调用
btns[0].onclick = add;
btns[1].onclick = subtract;
btns[2].onclick = multiply;
btns[3].onclick = divide;

//add
function add(){
sign.innerHTML = ' + ';
//dom取到的值为字符串,字符串相加会变拼接,需要转换成数值
resultOutput.innerHTML = +formerInput.value + +laterInput.value;
}
//subtract
function subtract(){
sign.innerHTML = ' - ';
//不用转换,因为字符串不能相减
resultOutput.innerHTML = formerInput.value - laterInput.value
}
//multiply
function multiply(){
sign.innerHTML = ' × ';
resultOutput.innerHTML = formerInput.value * laterInput.value;
}
function divide(){
sign.innerHTML = ' ÷ ';
resultOutput.innerHTML =+formerInput.value / laterInput.value;
}

</script>

改进二(循环绑定)

假若需要绑定的按钮过多,那么可以使用循环来进行事件绑定。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
//绑定事件,传的函数名
/*btns[0].onclick = add;
btns[1].onclick = subtract;
btns[2].onclick = multiply;
btns[3].onclick = divide;*/
//改用循环
for(var i = 0;i<btns.length;i++){
btns[i].onclick = function(){
switch(this.name){
case 'add':
add();
break;
case 'subtract':
subtract();
break;
case 'multiply':
multiply();
break;
case 'divide':
divide();
break;
}
};
}

改进三(提取函数)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
<script type="text/javascript">
//获取元素
var calculator = document.querySelector('#calculator');
var formerInput = calculator.querySelector(".formerInput");
var laterInput = calculator.querySelector(".laterInput");
var sign= calculator.querySelector(".sign");
var resultOutput = calculator.querySelector(".resultOutput");
var btns = calculator.querySelectorAll(".btn");

each(btns,function(index,elem){
elem.onclick = function(){
switch(this.name){
case 'add':
addHandler();
break;
case 'subtract':
subtractHandler();
break;
case 'multiply':
multiplyHandler();
break;
case 'divide':
divideHandler();
break;
}
};
});

//遍历
function each(array,fn){
for(var i = 0;i < array.length;i++){
fn(i,array[i]);
}
}
//更新符号
function updateSign(symbol){
sign.innerHTML = symbol;
}

//计算加法
function add(num1,num2){
return +num1 + +num2;
}
//计算减法
function subtract(num1,num2){
return num1 - num2;
}
//计算乘法
function multiply(num1,num2){
return num1 * num2;
}
//计算除法
function divide(num1,num2){
return num1 / num2;
}

//输出结果
function outputResult(result){
resultOutput.innerHTML = result;
}

//add
function addHandler(){
updateSign('+');
//dom取到的值为字符串,字符串相加会变拼接,需要转换成数值
outputResult(add(formerInput.value,laterInput.value)) ;
}
//subtract
function subtractHandler(){
updateSign('-');
//不用转换,因为字符串不能相减
outputResult(subtract(formerInput.value,laterInput.value));
}
//multiply
function multiplyHandler(){
updateSign(' × ');
outputResult(multiply(formerInput.value,laterInput.value));
}
//divide
function divideHandler(){
updateSign(' ÷ ');
outputResult(divide(formerInput.value,laterInput.value));
}

</script>

改进四(管理代码)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
<script type="text/javascript">
//获取元素
var wrapElem = document.querySelector('#calculator');
var calculatorElem = {
formerInput: wrapElem.querySelector(".formerInput"),
laterInput: wrapElem.querySelector(".laterInput"),
sign: wrapElem.querySelector(".sign"),
resultOutput: wrapElem.querySelector(".resultOutput"),
btns: wrapElem.querySelectorAll(".btn")
}

each(calculatorElem.btns,function(index,elem){
elem.onclick = function(){
switch(this.name){
case 'add':
addHandler();
break;
case 'subtract':
subtractHandler();
break;
case 'multiply':
multiplyHandler();
break;
case 'divide':
divideHandler();
break;
}
};
});


//遍历
function each(array,fn){
for(var i = 0;i < array.length;i++){
fn(i,array[i]);
}
}

//更新符号
function updateSign(symbol){
calculatorElem.sign.innerHTML = symbol;
}

var operation = {
//计算加法
add: function(num1,num2){
return +num1 + +num2;
},
//计算减法
subtract: function(num1,num2){
return num1 - num2;
},
//计算乘法
multiply: function(num1,num2){
return num1 * num2;
},
//计算除法
divide: function(num1,num2){
return num1 / num2;
}
};

//输出结果
function outputResult(result){
calculatorElem.resultOutput.innerHTML = result;
}

//add
function addHandler(){
updateSign('+');
//dom取到的值为字符串,字符串相加会变拼接,需要转换成数值
outputResult(operation.add(calculatorElem.formerInput.value,calculatorElem.laterInput.value)) ;
}
//subtract
function subtractHandler(){
updateSign('-');
//不用转换,因为字符串不能相减
outputResult(operation.subtract(calculatorElem.formerInput.value,calculatorElem.laterInput.value));
}
//multiply
function multiplyHandler(){
updateSign(' × ');
outputResult(operation.multiply(calculatorElem.formerInput.value,calculatorElem.laterInput.value));
}
//divide
function divideHandler(){
updateSign(' ÷ ');
outputResult(operation.divide(calculatorElem.formerInput.value,calculatorElem.laterInput.value));
}
</script>

改进五(OCP开放与封闭原则)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
<script type="text/javascript">
//获取元素
var wrapElem = document.querySelector('#calculator');
var calculatorElem = {
formerInput: wrapElem.querySelector(".formerInput"),
laterInput: wrapElem.querySelector(".laterInput"),
sign: wrapElem.querySelector(".sign"),
resultOutput: wrapElem.querySelector(".resultOutput"),
btns: wrapElem.querySelectorAll(".btn")
}

each(calculatorElem.btns,function(index,elem){
elem.onclick = function(){
updateSign(this.value);
outputResult(operate(this.name,calculatorElem.formerInput.value,calculatorElem.laterInput.value));
};
});


//遍历
function each(array,fn){
for(var i = 0;i < array.length;i++){
fn(i,array[i]);
}
}

//更新符号
function updateSign(symbol){
calculatorElem.sign.innerHTML = symbol;
}

//运算
function operate(type,num1,num2){
if(!operation[type]) throw new Error("不存在名为" + type +"的运算方法!");
return operation[type](num1,num2);
}

var operation = {
//计算加法
add: function(num1,num2){
return +num1 + +num2;
},
//计算减法
subtract: function(num1,num2){
return num1 - num2;
},
//计算乘法
multiply: function(num1,num2){
return num1 * num2;
},
//计算除法
divide: function(num1,num2){
return num1 / num2;
},
mod: function(num1,num2){
return num1 % num2;
},
addOperation: function(type,fn){
if(!this[type]){
this[type] = fn;
}
return this;
}
};

operation.addOperation('power',function(base,power){
return Math.pow(base,power);
});

//输出结果
function outputResult(result){
calculatorElem.resultOutput.innerHTML = result;
}

</script>