如何在自制JavaScript计算器中实现多运算串联及优先级支持?
JavaScript计算器:修复连续运算与优先级问题 + 代码优化
问题根源分析
原代码的核心缺陷:
- 连续运算逻辑错误:
chosenOperator被覆盖为单个运算函数,reduce仅能处理两个操作数,无法支持多步连续运算 - 无运算优先级:所有运算按输入顺序执行,不遵循乘除优先的数学规则
- 状态管理冗余:多个临时数组(
tempExpression、tempExpressionFiltered等)增加复杂度,且数据与屏幕显示易不同步 - 交互漏洞:小数点处理仅标记禁用但未实际阻止重复输入,删除操作时数据状态与屏幕内容不匹配
重构后的完整代码
HTML(修正嵌套结构,统一数据属性)
<p>CALCULATOR</p> <div class="container"> <div class="screen"> <div class="previous-operand"></div> <div class="current-operand"></div> </div> <div class="row"> <button type="button" data-action="delete">delete</button> <button type="button" data-action="clear">clear</button> </div> <div class="row"> <button type="button" data-action="number">7</button> <button type="button" data-action="number">8</button> <button type="button" data-action="number">9</button> <button type="button" data-action="operator">/</button> </div> <div class="row"> <button type="button" data-action="number">4</button> <button type="button" data-action="number">5</button> <button type="button" data-action="number">6</button> <button type="button" data-action="operator">*</button> </div> <div class="row"> <button type="button" data-action="number">1</button> <button type="button" data-action="number">2</button> <button type="button" data-action="number">3</button> <button type="button" data-action="operator">-</button> </div> <div class="row"> <button type="button" data-action="number">0</button> <button type="button" data-action="decimal">.</button> <button type="button" data-action="equals">=</button> <button type="button" data-action="operator">+</button> </div> </div>
CSS(优化布局与显示效果)
* { box-sizing: border-box; margin: 0; padding: 0; } .container { width: 200px; margin: 1rem; } .screen { background-color: lightgray; width: 100%; height: 60px; padding: 0.5rem; text-align: right; display: flex; flex-direction: column; justify-content: space-between; } .previous-operand { font-size: 0.9rem; opacity: 0.7; } .current-operand { font-size: 1.2rem; } button { width: 50px; height: 50px; border: 1px solid #ddd; cursor: pointer; font-size: 1rem; } button:hover { background-color: #f0f0f0; } .row { display: flex; }
JavaScript(核心逻辑重构)
// DOM元素获取 const screen = document.querySelector('.screen'); const previousOperandEl = screen.querySelector('.previous-operand'); const currentOperandEl = screen.querySelector('.current-operand'); const buttons = document.querySelectorAll('button'); // 计算器核心状态 let currentOperand = ''; let previousOperand = ''; let operation = undefined; let expression = []; // 存储完整运算序列:[数字, 操作符, 数字, ...] // 运算函数映射 const operations = { '+': (a, b) => a + b, '-': (a, b) => a - b, '*': (a, b) => a * b, '/': (a, b) => b !== 0 ? a / b : 'Error' }; // 更新屏幕显示 function updateDisplay() { currentOperandEl.textContent = currentOperand || '0'; previousOperandEl.textContent = operation ? `${previousOperand} ${operation}` : ''; } // 追加数字/小数点 function appendNumber(value) { if (value === '.' && currentOperand.includes('.')) return; currentOperand += value; updateDisplay(); } // 选择操作符 function chooseOperator(op) { if (currentOperand === '') return; // 已有未完成运算时,先计算前一步 if (previousOperand !== '') compute(); operation = op; previousOperand = currentOperand; expression.push(parseFloat(currentOperand), op); currentOperand = ''; updateDisplay(); } // 核心计算:处理运算优先级 function compute() { if (currentOperand === '') return; expression.push(parseFloat(currentOperand)); // 第一步:计算所有乘除 let temp = []; for (let i = 0; i < expression.length; i++) { if (expression[i] === '*' || expression[i] === '/') { const prev = temp.pop(); const next = expression[i + 1]; temp.push(operations[expression[i]](prev, next)); i++; // 跳过已计算的下一个数字 } else { temp.push(expression[i]); } } // 第二步:计算所有加减 let result = temp[0]; for (let i = 1; i < temp.length; i += 2) { result = operations[temp[i]](result, temp[i + 1]); } // 更新状态,支持连续运算 currentOperand = result.toString(); previousOperand = ''; operation = undefined; expression = [result]; // 将结果作为下一次运算的起始 updateDisplay(); } // 清除所有状态 function clearAll() { currentOperand = ''; previousOperand = ''; operation = undefined; expression = []; updateDisplay(); } // 删除最后一位输入 function deleteLast() { currentOperand = currentOperand.slice(0, -1); updateDisplay(); } // 绑定按钮事件 buttons.forEach(button => { button.addEventListener('click', () => { const action = button.dataset.action; const value = button.textContent; switch(action) { case 'number': case 'decimal': appendNumber(value); break; case 'operator': chooseOperator(value); break; case 'equals': compute(); break; case 'clear': clearAll(); break; case 'delete': deleteLast(); break; } }); });
关键优化点说明
- 状态简化:仅用3个核心变量管理计算器状态,删除所有冗余临时数组,逻辑更清晰
- 运算优先级实现:分两步计算,先处理乘除再处理加减,完全符合数学运算规则
- 连续运算支持:按下操作符时自动完成前一步运算,将结果作为新运算的起始,支持
10+20+10这类连续输入 - 交互体验优化:阻止重复小数点输入、删除操作仅影响当前输入、分区域显示运算过程
- 代码结构优化:用对象统一管理运算函数,避免重复if-else判断;事件绑定用switch集中处理,可读性更强
内容的提问来源于stack exchange,提问作者kalper
相关产品推荐
相关产品推荐

