JavaScript计算器链式运算场景下等号功能异常排查求助
我仔细扒了你的代码,发现几个关键坑导致多步运算时等号功能抽风,咱们一步步把这些坑填上:
1. 要命的拼写错误
你在减法按钮的逻辑里把运算类型写成了"subract"(少了个t),但calcFunc里的方法名是subtract,等号判断的时候也用的是"subract",这直接导致减法运算时等号分支根本匹配不到,等于白忙活。
修复:把所有"subract"改成"subtract",保持命名完全一致。
2. 等号按钮的逻辑混乱到离谱
在减法、乘法、除法的等号分支里,你先算出结果赋值给mathHoldOne.num,转头就把它设为0,这不是刚拿到结果就扔了吗?而且和加法的重置逻辑完全不一致:
// 错误示例(减法分支) mathHoldOne.num = (mathHoldOne.num - mathHoldTwo.num); mathHoldTwo.num = 0; mathHoldOne.num = 0; // 这里直接把结果清零了! mathHoldOne.set = false;
修复:统一等号按钮的逻辑,计算完结果后把它存到mathHoldOne里,方便后续继续链式运算,只重置mathHoldTwo和运算类型:
case('cell equal'): mathHoldTwo.num = parseInt(screenValue.innerHTML); let result; switch(mathType.type) { case "add": result = calcFunc.add(mathHoldOne.num, mathHoldTwo.num); break; case "subtract": result = calcFunc.subtract(mathHoldOne.num, mathHoldTwo.num); break; case "multiply": result = calcFunc.multiply(mathHoldOne.num, mathHoldTwo.num); break; case "divide": result = calcFunc.divide(mathHoldOne.num, mathHoldTwo.num); break; default: result = screenValue.innerHTML; // 处理直接点等号的情况 } screenValue.innerHTML = result; miniView.innerHTML = result; // 保存结果,支持后续继续运算 mathHoldOne.num = result; mathHoldOne.set = true; mathHoldTwo.num = 0; mathHoldTwo.set = false; mathType.type = undefined; break;
3. 重复绑定点击事件导致屏幕乱显示
你的updateView方法里给.js-container绑了一次点击事件用来更新屏幕,btnHandle里又绑了一次用来处理按钮逻辑。这会导致点击数字按钮时,屏幕重复显示内容(比如点1显示11),parseInt解析的数值直接出错,运算结果当然不对。
修复:删掉updateView里的点击事件,把屏幕更新逻辑整合到btnHandle的点击事件里,排除清除、等号、运算符号这些特殊按钮:
// 移除updateView里的这段代码: /* const jsContainer = document.getElementsByClassName('js-container')[0]; jsContainer.addEventListener('click', function (e) { let show = e.target.innerHTML; viewScreen.innerHTML += show; }); */ // 在btnHandle的点击事件开头加这段: btnHandler.addEventListener('click', function (event) { let btn = event.target; let screenValue = document.querySelector('.js-view'); let miniView = document.querySelector('.mini-view'); // 更新屏幕显示(只处理数字按钮) const specialBtns = ['cell clear', 'cell equal', 'cell math multiply', 'cell math divide', 'cell math add', 'cell math subtract']; if (!specialBtns.includes(btn.className)) { screenValue.innerHTML += btn.innerHTML; } // 原来的switch逻辑... });
4. 乘法的拼写错误
你在乘法按钮里把mathType.type设成了"mulitply"(少了个p),但等号判断用的是"multiply",这也会导致乘法的等号分支匹配失败。
修复:把mathType.type = "mulitply"改成mathType.type = "multiply"。
修复后的完整代码
const view = { updateView: function () { let viewScreen = document.getElementsByClassName('js-view')[0]; let miniView = document.getElementsByClassName('mini-view')[0]; viewScreen.innerHTML = ''; miniView.innerHTML = ''; }, btnHandle: function () { let mathType = {"type": undefined}; let mathHoldOne = {"num": 0, "set": false}; let mathHoldTwo = {"num": 0, "set": false}; let btnHandler = document.querySelector('.js-container'); btnHandler.addEventListener('click', function (event) { let btn = event.target; let screenValue = document.querySelector('.js-view'); let miniView = document.querySelector('.mini-view'); // 更新屏幕显示(仅数字按钮) const specialBtns = ['cell clear', 'cell equal', 'cell math multiply', 'cell math divide', 'cell math add', 'cell math subtract']; if (!specialBtns.includes(btn.className)) { screenValue.innerHTML += btn.innerHTML; } switch (btn.className) { case('cell clear'): screenValue.innerHTML = ''; miniView.innerHTML = ''; mathHoldOne.num = 0; mathHoldOne.set = false; mathHoldTwo.num = 0; mathHoldTwo.set = false; mathType.type = undefined; break; case('cell math multiply'): if (mathHoldOne.set) { mathHoldTwo.num = parseInt(screenValue.innerHTML); mathHoldTwo.set = true; screenValue.innerHTML = ''; } else { mathHoldOne.num = parseInt(screenValue.innerHTML); mathHoldOne.set = true; screenValue.innerHTML = ''; mathType.type = "multiply"; // 修复拼写错误 } if (mathHoldOne.set && mathHoldTwo.set) { for (let name in calcFunc) { if (mathType.type === name) { const tempResult = calcFunc[name](mathHoldOne.num, mathHoldTwo.num); miniView.innerHTML = tempResult; mathHoldOne.num = tempResult; } } mathHoldTwo.num = 0; mathHoldTwo.set = false; mathType.type = 'multiply'; } break; case('cell math divide'): if (mathHoldOne.set) { mathHoldTwo.num = parseInt(screenValue.innerHTML); mathHoldTwo.set = true; screenValue.innerHTML = ''; } else { mathHoldOne.num = parseInt(screenValue.innerHTML); mathHoldOne.set = true; screenValue.innerHTML = ''; mathType.type = "divide"; } if (mathHoldOne.set && mathHoldTwo.set) { for (let name in calcFunc) { if (mathType.type === name) { const tempResult = calcFunc[name](mathHoldOne.num, mathHoldTwo.num); miniView.innerHTML = tempResult; mathHoldOne.num = tempResult; } } mathHoldTwo.num = 0; mathHoldTwo.set = false; mathType.type = 'divide'; } break; case('cell math add'): if (mathHoldOne.set) { mathHoldTwo.num = parseInt(screenValue.innerHTML); mathHoldTwo.set = true; screenValue.innerHTML = ''; } else { mathHoldOne.num = parseInt(screenValue.innerHTML); mathHoldOne.set = true; screenValue.innerHTML = ''; mathType.type = "add"; } if (mathHoldOne.set && mathHoldTwo.set) { for (let name in calcFunc) { if (mathType.type === name) { const tempResult = calcFunc[name](mathHoldOne.num, mathHoldTwo.num); miniView.innerHTML = tempResult; mathHoldOne.num = tempResult; } } mathHoldTwo.num = 0; mathHoldTwo.set = false; mathType.type = 'add'; } break; case('cell math subtract'): if (mathHoldOne.set) { mathHoldTwo.num = parseInt(screenValue.innerHTML); mathHoldTwo.set = true; screenValue.innerHTML = ''; } else { mathHoldOne.num = parseInt(screenValue.innerHTML); mathHoldOne.set = true; screenValue.innerHTML = ''; mathType.type = "subtract"; // 修复拼写错误 } if (mathHoldOne.set && mathHoldTwo.set) { for (let name in calcFunc) { if (mathType.type === name) { const tempResult = calcFunc[name](mathHoldOne.num, mathHoldTwo.num); miniView.innerHTML = tempResult; mathHoldOne.num = tempResult; } } mathHoldTwo.num = 0; mathHoldTwo.set = false; mathType.type = 'subtract'; } break; case('cell equal'): mathHoldTwo.num = parseInt(screenValue.innerHTML); let result; switch(mathType.type) { case "add": result = calcFunc.add(mathHoldOne.num, mathHoldTwo.num); break; case "subtract": result = calcFunc.subtract(mathHoldOne.num, mathHoldTwo.num); break; case "multiply": result = calcFunc.multiply(mathHoldOne.num, mathHoldTwo.num); break; case "divide": result = calcFunc.divide(mathHoldOne.num, mathHoldTwo.num); break; default: result = screenValue.innerHTML; } screenValue.innerHTML = result; miniView.innerHTML = result; mathHoldOne.num = result; mathHoldOne.set = true; mathHoldTwo.num = 0; mathHoldTwo.set = false; mathType.type = undefined; break; } console.log(mathHoldOne, mathHoldTwo, mathType.type); }) } }; view.updateView(); view.btnHandle(); const calcFunc = { add: function (x, y) { return x + y; }, subtract: function (x, y) { return x - y; }, multiply: function (x, y) { return x * y; }, divide: function (x, y) { return x / y; }, clear: function () { let view = document.querySelector('.js-view'); view.innerHTML = ''; } }
现在测试下多步运算,比如2 + 3 * 4(先算2+3得5,再乘4得20,点等号应该显示20),或者10 - 2 + 5,等号按钮都能正确返回最终结果了。
内容的提问来源于stack exchange,提问作者Tchbell

