计算器开发问题:operate函数触发异常及input值显示不符
计算器输入值与控制台打印不一致的问题
我开发了一个计算器,希望当所有值均不为空字符串时调用operate()函数。例如输入5 + 5时,第二个数字输入完成后应立即调用operate()。
但现在遇到一个问题:输入框显示5 + 5 ,但用console.log打印input.value时得到的是5 + ,且secondNumbers = "",我不确定原因是什么。

从图片右侧控制台可以看到,console.log(inputdisplay.value)的结果是4 + 。
我不知道这是JavaScript本身的问题,还是我的代码有误。
我的代码:
JavaScript代码
const buttons = document.querySelectorAll('button'); const inputdisplay = document.querySelector('.input-display'); var firstNumbers; var secondNumbers; var operator; buttons.forEach(function(button) { button.addEventListener('click', function(e) { firstNumbers = inputdisplay.value.split(" ")[0] operator = inputdisplay.value.split(" ")[1] secondNumbers = inputdisplay.value.split(" ")[2] console.log(inputdisplay.value) console.log(secondNumbers) if (typeof(secondNumbers) === "string" && secondNumbers !== "") { console.log("ran") inputdisplay.value = operate() } else if (button.classList.contains("AC")) { inputdisplay.value = "" return } else if (button.classList.contains("equals")) { inputdisplay.value = operate() } else if (button.classList.contains("operator")) { inputdisplay.value += ` ${button.innerText} ` } else { inputdisplay.value += button.innerText } }) }) function operate() { intFirstNumbers = parseFloat(firstNumbers) intSecondNumbers = parseFloat(secondNumbers) try { switch (operator) { case "+": return intFirstNumbers + intSecondNumbers case "-": return intFirstNumbers - intSecondNumbers case "*": return intFirstNumbers * intSecondNumbers case "/": return intFirstNumbers / intSecondNumbers } } catch (e) { return "Error: " + e.message } }
HTML代码
<div class="container"> <input readonly class="input-display" type="text"> <div class="grid"> <div class="numberGrid"> <div class="row-1"> <button class=" button 1">1</button> <button class=" button 2">2</button> <button class=" button 3">3</button> <button class=" button 4">4</button> </div> <div class=" row-2"> <button class=" button 5">5</button> <button class=" button 6">6</button> <button class=" button 7">7</button> <button class=" button 8">8</button> </div> <div class="row-3"> <button class=" button 9">9</button> <button class=" button 0">0</button> <button class=" button decimal ">.</button> </div> </div> <div class="operatorGrid"> <div class="row-4"> <button class=" button sum operator"> + </button> <button class=" button subtract operator"> - </button> <button class=" button multiply operator"> * </button> <button class=" button divide operator"> / </button> <button class=" button backspace operator"> -></button> <button class=" button equals"> = </button> <button class=" button AC">AC</button> </div> </div> </div> </div>
问题原因
代码逻辑顺序完全搞反了:你先读取了输入框的旧值,然后才把新点击的内容追加到输入框里。
比如点击第二个数字时,你先执行了firstNumbers = inputdisplay.value.split(" ")[0]这类读取操作,此时输入框里还是5 + ,还没把新数字加进去,所以secondNumbers是空的。之后才执行inputdisplay.value += button.innerText,输入框才显示5 + 5,但控制台已经打印完旧值了,所以会出现输入框显示新值、控制台输出旧值的矛盾现象。
解决方法
把读取输入框值、判断是否调用operate()的逻辑,放到追加内容到输入框之后,同时调整判断逻辑避免重复计算:
修改后的JavaScript代码:
const buttons = document.querySelectorAll('button'); const inputdisplay = document.querySelector('.input-display'); var firstNumbers; var secondNumbers; var operator; buttons.forEach(function(button) { button.addEventListener('click', function(e) { // 先处理输入内容的追加 if (button.classList.contains("AC")) { inputdisplay.value = "" return } else if (button.classList.contains("operator")) { inputdisplay.value += ` ${button.innerText} ` } else if (!button.classList.contains("equals")) { // 数字和小数点按钮 inputdisplay.value += button.innerText } // 读取最新的输入框值 const parts = inputdisplay.value.split(" ") firstNumbers = parts[0] operator = parts[1] secondNumbers = parts[2] console.log(inputdisplay.value) console.log(secondNumbers) // 判断是否满足自动计算条件 if (secondNumbers && secondNumbers.trim() !== "" && !button.classList.contains("operator")) { console.log("ran") inputdisplay.value = operate() } else if (button.classList.contains("equals")) { inputdisplay.value = operate() } }) }) function operate() { // 用const声明变量,避免污染全局作用域 const intFirstNumbers = parseFloat(firstNumbers) const intSecondNumbers = parseFloat(secondNumbers) try { switch (operator) { case "+": return intFirstNumbers + intSecondNumbers case "-": return intFirstNumbers - intSecondNumbers case "*": return intFirstNumbers * intSecondNumbers case "/": return intFirstNumbers / intSecondNumbers default: return "Invalid operator" } } catch (e) { return "Error: " + e.message } }
额外优化点
- 给
operate()里的变量加上const,避免意外修改全局变量。 - 增加
default分支处理无效运算符的情况。 - 判断
secondNumbers时用trim(),避免空格导致的误判。 - 把输入内容追加的逻辑前置,确保读取的是最新的输入值。
内容的提问来源于stack exchange,提问作者Josh knon
相关产品推荐
相关产品推荐

