-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathmain.js
More file actions
233 lines (198 loc) · 6.05 KB
/
main.js
File metadata and controls
233 lines (198 loc) · 6.05 KB
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
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
window.onload = function () {
var container = document.querySelector('.container'),
screen = document.querySelector('.display'),
number = document.querySelector('.number-key'),
operator = document.querySelector('.operator-key'),
ac = document.querySelector('#ac'),
del = document.querySelector('#del')
if(!container || !screen || !number || !operator || !ac || !del) {
console.log("Didn't find dom element as expected!")
return false
}
var calculator = {
_value: '',
lastKey: '',
get value () {
return this._value
},
set value (val) {
// DOM 绑定,每次_value的值变化都会触发DOM刷新
screen.textContent = val
this._value = val
}
}
// 监听按键点击
container.addEventListener('click', action.bind(calculator))
}
/* event listener */
function action (event) {
var target = event.target,
className = target.className,
key = target.textContent,
self = this
switch(className) {
case "number-key":
// 避免出现 连续多个0的情况
if(self.value === '0' && key === '0') {
return false
}
self.value += key
break
case "operator-key":
if(self.lastKey.keyValue === key) {
return false
}
self.value += key
break
case "function-key":
// 清空全部状态
if(key === 'AC') {
self.value = ''
self.lastKey = ''
} else {
// 后退至上一步操作
var length = self.value.length
self.value = length === 0 ? '' : self.value.slice(0, -1)
self.lastKey = self.value[length-1]
}
break
// 在按下等号键的时候判断输入并触发整个计算流程。
case "equal-key":
var computeResult = exec(self.value)
if (computeResult) {
self.value = computeResult.toString()
} else {
ac.click() //此次计算终结,清空状态值
document.querySelector('.display').textContent = "0 can't set as divisor"
}
break
}
// 处理完输入后,更新lastKey
self.lastKey = key
}
/* core calculation */
function exec (str) {
// 之前想要将括号嵌套纳入处理范围时想到的代码,试了之后发现并不是想象中那样简单
// if (str.includes('(')) {
// var leftBracketIndexs = [],
// rigthBracketIndexs = []
// // 记录左右括号的索引值
// for (var i = 0, n = str.length; i < n; i++) {
// if (str[i] === '(') {
// leftBracketIndexs.push(i)
// } else if (str[i] === ')') {
// rigthBracketIndexs.push(i+1)
// }
// }
// // 输入不合法,括号未成对出现
// if(leftBracketIndexs.length !== rigthBracketIndexs.length) {
// return false
// }
// for (var i = 0, length = leftBracketIndexs.length; i < length; i++) {
// var temp = str.slice(leftBracketIndexs[i], rigthBracketIndexs[i])
// // tempResult = splitStr(temp)
// console.log(temp)
// }
// }
var executedStr = bracketHandler(str)
if(executedStr.includes('+') || executedStr.includes('-') || executedStr.includes('*') || executedStr.includes('/')) {
var splitArr = splitStr(executedStr),
result = findOperator(splitArr)
return result ? result : false
}
// 整个表达式都在括号内
return executedStr
}
// 计算括号内的表达式
// 学习了递归的用法,完成的函数要return下一次的调用,最后的返回值才能逐级返回。
function bracketHandler (inpustr) {
var regExp = /\(([^)]+)\)/,
output = inpustr
if(regExp.test(inpustr)) {
var temp = regExp.exec(inpustr)[1], // 取出括号内的字符串
item = '(' + temp + ')'
var splitArr = splitStr(temp),
result = findOperator(splitArr)
output = inpustr.replace(item, result.toString())
return bracketHandler(output)
} else {
return output
}
}
//sterp1 将字符串分割为实际数据与操作符的集合
function splitStr (str) {
var operators = ['+', '-', '*', '/'],
start = 0, // 数据的起始位置
end = 0, // 数据的终点位置
splitedArr = [] // 映射的目标数组
for(var i = 0, n = str.length; i < n; i++) {
if (operators.includes(str[i])) {
start = end === 0 ? 0 : end + 1
end = i
if (i === 0) continue // 第一个字符为操作符时,结束当前循环
splitedArr.push(parseFloat(str.slice(start, end)))
splitedArr.push(str[i])
}
if (i === n - 1) {
splitedArr.push(parseFloat(str.slice(end+1)))
}
}
return splitedArr
}
/*
* 识别运算符并逐3个进行计算
* 保证乘除法优先级
*/
function findOperator (arr) {
var result = 0
// 乘除法优先级高,先检索乘、除号做运算
if (arr.includes('*') || arr.includes('/')) {
for (var i = 0; i < arr.length; i++) {
// 当数组规模塌缩为3时,直接进行最后一次运算
if (arr.length === 3) {
result = stupidCompute(arr[0], arr[1], arr[2])
break
}
// debugger
if (arr[i] === '*' || arr[i] === '/') {
var computed = stupidCompute(arr[i-1], arr[i], arr[i+1])
// 除数为0时,打破函数链
if (computed === false) {
return false
}
arr.splice(i-1,3,computed)
i--
}
}
}
// 加减法运算
for (var i = 0; i < arr.length; i++) {
if (arr.length === 3) {
result = stupidCompute(arr[0], arr[1], arr[2])
break
}
if (arr[i] === '+' || arr[i] === '-') {
// debugger
var computed = stupidCompute(arr[i-1], arr[i], arr[i+1])
arr.splice(i-1,3,computed)
i--
}
}
return result
}
// 执行最基本的运算
function stupidCompute(number1, operator, number2) {
switch(operator) {
case '+' :
return number1 + number2
case '-' :
return number1 - number2
case '*' :
return number1 * number2
case '/' :
if (number2 === 0) {
return false
}
return number1 / number2
}
}