You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

JavaScript计算器连续运算功能实现求助:点击运算符自动计算

问题描述

我正在开发一个简易JavaScript计算器练习项目,卡壳一周了。想实现点击运算符时自动连续计算的功能:比如输入2 + 4 * 5 / 15,每次按下运算符(比如输入2+4后按'x',要把结果存入previousNum变量,再用这个结果乘5,以此类推),但现有逻辑代码无法生效。

我的问题代码片段:

if (!isNaN(previousNum)) { previousNum = currentNum; displayPrevResult.textContent = operate(operator, previousNum, currentNum); }

目前还没添加等号、清除和小数点功能,优先解决这个连续计算的问题。作为编程新手,试了多种方法都没用,求指导实现该功能。


完整代码

JavaScript代码

/* PSEUDO:

    CREATE A VARIABLE TO STORE THE CURRENT NUMBER, PREVIOUS NUMBER AND OPERATE SYMBOL.

    WHEN CLICK A NUMBER STORES IT IN A CURRENT NUMBER VARIABLE.

    WHEN CLICKING OPERATOR AND SELECT A SECOND NUMBER REPLACES CURRENT NUMBER WITH NEW NUMBER
    AND STORES OLD NUMBER IN THE PREVIOUS NUMBER VARIABLE.

    WHEN CLICKING OPERATOR AGAIN IT OPERATES THE CURRENT NUMBER BY THE PREVIOUS NUMBER, 
    STORES THE RESULT IN THE PREVIOUS NUMBER VARIABLE AND EMPTY THE CURRENT NUMBER VARIABLE.

    WHEN PRESSING EQUAL BUTTON OPERATES CURRENT NUMBER BY PREVIOUS NUMBER AND STORES IT IN PREVIOUS NUMBER VARIABLE.
    
        > IF CURRENT NUMBER AND PREVIOUS NUMBER VARIABLE HAS A NUMBER THEN EQUAL BUTTON OPERATES
        > IF NOT, EQUAL BUTTON DOES NOT WORK.

    IF DIVIDE CURRENT NUMBER BY 0 THEN THROWS AN ERROR.

*/

const displayPrevResult = document.querySelector('.prev-result');
const displayCurrentResult = document.querySelector('.current-result');
const equal = document.querySelector('.equal');
const decimal = document.querySelector('.decimal');
const clear = document.querySelector('.clear');

const numberBtn = document.querySelectorAll('.number');
const operatorBtn = document.querySelectorAll('.operator');

let currentNum = '';
let previousNum = '';
let operator = '';

numberBtn.forEach((button) => {
    button.addEventListener('click', (event) => {
        getNum(event.target.textContent);
    });
});

operatorBtn.forEach((button) => {
    button.addEventListener('click', (event) => {
        getOp(event.target.textContent);
    });
});

function getNum(num) {
    currentNum += num;
    currentNum = parseFloat(currentNum);
    displayCurrentResult.textContent = currentNum;
}

function getOp(op) {
    operator = op;
    previousNum = currentNum;
    displayPrevResult.textContent = previousNum + ' ' + operator;
    currentNum = '';

    if (!isNaN(previousNum)) {
        previousNum = currentNum;
        displayPrevResult.textContent = operate(operator, previousNum, currentNum);
    }    
}

function operate(op, a, b) {
    switch(op) {
        case '+':
            return add(a, b);
        break;
        case '-':
            return subtract(a, b);
        break;
        case 'x':
            return multiply(a, b);
        break;
        case '÷':
            return divide(a, b);
        default:
    }
}

//Operating functions
function add(a, b) {
    return a + b;
}

function subtract(a, b) {
    return a - b;
}

function multiply(a, b) {
    return a * b;
}

function divide(a, b) {
    return a / b;
}

CSS代码

body {
    width: 100vw;
    height: 100vh;
    display: flex;
    justify-content: center;
    align-items: center;
}

.calcContainer {
    background: linear-gradient(276deg, #40a179, #77cea9);
    padding: 1em;
    border-radius: 5px;
    border: 1px solid #000;
}

button {
    padding: 1em;
    margin: 0.1em;
    width: 40px;
    background: #a2ffaf;
    border: 1px solid #fff;
    border-radius: 3px;
    cursor: pointer;
}

button:hover {
    background: #72e782;
}

.clr {
    background: #87e4bd;
}

.clr:hover {
    background: #53ad88;
}

.clear {
    margin: 0em 0.1em 0.5em 0.5em;
    padding: 0;
}

.output-clear-container {
    display: flex;
}

.output {
    flex-grow: 1;
    height: 40px;
    background: #c2fcca;
    border-radius: 5px;
    border: 1px solid #fff;
    display: flex;
    flex-direction: column;
    align-items: flex-end;
    justify-content: flex-end;
    padding-right: 0.5em;
    margin-bottom: 0.5em;
}

.par {
    margin-bottom: 0.3em;
}

.prev-result {
    font-size: 14px;
    padding-bottom: 0.3em;
    color:#40a179;
}

.current-result {
    font-size: 18px;
}

HTML代码

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <link rel="stylesheet" href="styles.css">
    <script src="main.js" defer></script>
    <title>Calculator</title>
</head>
<body>
    <div class="calcContainer">
        <div class="output-clear-container">
            <div class="output">
                <div class="prev-result"></div>
                <div class="current-result">0</div>
            </div>
            <button class="clear">AC</button>
        </div>
            <div class="par">
                <button class="number">7</button>
                <button class="number">8</button>
                <button class="number">9</button>
                <button class="operator clr">÷</button>
            </div>
            <div class="par">
                <button class="number">4</button>
                <button class="number">5</button>
                <button class="number">6</button>
                <button class="operator clr">x</button>
            </div>
            <div class="par">
                <button class="number">1</button>
                <button class="number">2</button>
                <button class="number">3</button>
                <button class="operator clr">-</button>
            </div>
            <div class="par">
                <button class="decimal clr">.</button>
                <button class="number">0</button>
                <button class="equal clr">=</button>
                <button class="operator clr">+</button>
            </div>
    </div>
</body>
</html>

解决方案

问题根源

你的getOp函数逻辑完全颠倒了:

  1. 点击运算符时,先把currentNum赋值给previousNum,接着清空currentNum,之后又用空的currentNum覆盖了previousNum,导致计算时传入的是无效值
  2. 连续计算的核心逻辑应该是:当已有历史计算数据(previousNum和operator都存在),先完成上一次计算,再将结果作为新的previousNum,最后保存新的运算符

修改后的关键代码

1. 修正getOp函数

function getOp(op) {
    // 已有历史计算数据时,先完成上一次运算
    if (previousNum !== '' && operator !== '' && currentNum !== '') {
        const result = operate(operator, parseFloat(previousNum), parseFloat(currentNum));
        previousNum = result.toString();
        displayPrevResult.textContent = previousNum + ' ' + op;
        currentNum = '';
    } else {
        // 第一次点击运算符,仅保存当前数和运算符
        previousNum = currentNum.toString();
        displayPrevResult.textContent = previousNum + ' ' + op;
        currentNum = '';
    }
    operator = op;
}

2. 调整getNum函数(避免空值转NaN)

function getNum(num) {
    currentNum += num;
    displayCurrentResult.textContent = currentNum;
}

逻辑说明

  1. 第一次点击运算符(如输入2后按+):保存previousNum为"2",运算符为"+",清空currentNum,等待输入下一个数
  2. 输入4后按x:此时三个变量都有值,先计算2+4=6,把previousNum设为"6",保存新运算符"x",清空currentNum,显示栏更新为"6 x"
  3. 输入5后按/:计算6*5=30,更新previousNum为"30",运算符设为"/",以此类推,实现连续计算

内容的提问来源于stack exchange,提问作者Quickpois0n

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.20 06:37:09