使用JavaScript开发一个简易计算器(附示例代码)

原创 2025-09-03 10:05:56编程技术
665

引言

在Web开发领域,JavaScript因其灵活性和强大的交互能力成为实现动态功能的核心技术。本文ZHANID工具网将通过构建一个简易计算器,系统讲解如何利用HTML、CSS和JavaScript完成一个完整的交互式应用。核心功能包括数字输入、运算符处理、计算结果展示及异常处理,重点涉及DOM操作、事件监听、状态管理和错误处理等关键技术点。

一、基础架构设计

1.1 HTML结构

计算器的基础布局需包含输入显示区域和按键区域。采用语义化标签提升可读性:

<!DOCTYPE html>
<html lang="zh-CN">
<head>
  <meta charset="UTF-8">
  <title>简易计算器</title>
  <link rel="stylesheet" href="styles.css">
</head>
<body>
  <div class="calculator">
    <div class="display" id="display">0</div>
    <div class="buttons">
      <!-- 数字按键 -->
      <button class="btn num" data-value="7">7</button>
      <button class="btn num" data-value="8">8</button>
      <!-- 其他按键... -->
    </div>
  </div>
  <script src="script.js"></script>
</body>
</html>

1.2 CSS样式设计

通过Flexbox实现响应式布局,确保计算器在不同设备上正常显示:

.calculator {
  width: 300px;
  margin: 50px auto;
  border-radius: 10px;
  overflow: hidden;
  box-shadow: 0 0 20px rgba(0,0,0,0.2);
}

.display {
  height: 80px;
  background: #222;
  color: white;
  font-size: 2.5em;
  text-align: right;
  padding: 10px;
  box-sizing: border-box;
}

.buttons {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: 1px;
  background: #eee;
}

.btn {
  height: 60px;
  border: none;
  font-size: 1.5em;
  cursor: pointer;
}

二、JavaScript核心逻辑实现

2.1 状态管理设计

采用模块化设计模式,将计算器状态封装在对象中:

const calculator = {
  displayValue: '0',
  firstOperand: null,
  waitingForSecondOperand: false,
  operator: null,
};

关键状态说明

状态字段 作用 示例值
displayValue 当前显示值 "123"
firstOperand 第一个操作数 5
waitingForSecondOperand 是否等待第二个操作数输入 true/false
operator 当前运算符 "+"

2.2 核心功能实现

2.2.1 更新显示函数

function updateDisplay() {
  const display = document.getElementById('display');
  display.textContent = calculator.displayValue;
}

2.2.2 数字输入处理

function inputDigit(digit) {
  if (calculator.waitingForSecondOperand) {
    calculator.displayValue = digit.toString();
    calculator.waitingForSecondOperand = false;
  } else {
    calculator.displayValue = 
      calculator.displayValue === '0' 
        ? digit.toString() 
        : calculator.displayValue + digit;
  }
}

2.2.3 运算符处理逻辑

function handleOperator(nextOperator) {
  const inputValue = parseFloat(calculator.displayValue);
  
  if (calculator.firstOperand === null) {
    calculator.firstOperand = inputValue;
  } else if (calculator.operator) {
    const result = calculate(
      calculator.firstOperand, 
      inputValue, 
      calculator.operator
    );
    calculator.displayValue = String(result);
    calculator.firstOperand = result;
  }
  
  calculator.waitingForSecondOperand = true;
  calculator.operator = nextOperator;
}

function calculate(a, b, op) {
  switch (op) {
    case '+': return a + b;
    case '-': return a - b;
    case '*': return a * b;
    case '/': return b === 0 ? NaN : a / b;
    default: return b;
  }
}

2.2.4 完整计算流程

function performCalculation() {
  if (
    calculator.operator === null ||
    calculator.waitingForSecondOperand
  ) {
    return;
  }
  
  const result = calculate(
    calculator.firstOperand,
    parseFloat(calculator.displayValue),
    calculator.operator
  );
  
  calculator.displayValue = String(result);
  calculator.operator = null;
  calculator.firstOperand = result;
  calculator.waitingForSecondOperand = true;
}

2.3 事件监听系统

通过数据属性实现按键功能绑定:

document.querySelector('.buttons').addEventListener('click', (event) => {
  const target = event.target;
  
  if (!target.matches('button')) return;
  
  if (target.classList.contains('num')) {
    inputDigit(parseInt(target.dataset.value));
  } else if (target.classList.contains('operator')) {
    handleOperator(target.dataset.value);
  } else if (target.classList.contains('equals')) {
    performCalculation();
  } else if (target.classList.contains('clear')) {
    resetCalculator();
  }
  
  updateDisplay();
});

三、异常处理机制

3.1 除零错误处理

function calculate(a, b, op) {
  switch (op) {
    case '/': 
      if (b === 0) {
        alert('错误:除数不能为零');
        return NaN;
      }
      return a / b;
    // 其他运算符...
  }
}

3.2 无效输入检测

function inputDecimalPoint() {
  if (calculator.waitingForSecondOperand) {
    calculator.displayValue = '0.';
    calculator.waitingForSecondOperand = false;
    return;
  }
  
  if (!calculator.displayValue.includes('.')) {
    calculator.displayValue += '.';
  }
}

3.3 完整重置功能

function resetCalculator() {
  Object.assign(calculator, {
    displayValue: '0',
    firstOperand: null,
    waitingForSecondOperand: false,
    operator: null
  });
}

四、功能扩展实现

4.1 百分比计算功能

function inputPercent() {
  const currentValue = parseFloat(calculator.displayValue);
  if (calculator.waitingForSecondOperand) {
    calculator.firstOperand = currentValue / 100;
    calculator.displayValue = String(calculator.firstOperand);
  } else {
    calculator.displayValue = String(currentValue / 100);
  }
}

4.2 正负号切换

function toggleSign() {
  const currentValue = parseFloat(calculator.displayValue);
  calculator.displayValue = String(currentValue * -1);
}

4.3 完整按键映射表

按键类型 对应方法 示例按钮
数字键 inputDigit() 0-9
运算符 handleOperator() +, -, *, /
等号 performCalculation() =
小数点 inputDecimalPoint() .
清除 resetCalculator() C
百分比 inputPercent() %
正负号 toggleSign() +/-

JavaScript

五、性能优化策略

5.1 防抖处理

对连续按键操作进行优化:

let debounceTimer;
function debouncedUpdate() {
  clearTimeout(debounceTimer);
  debounceTimer = setTimeout(() => {
    updateDisplay();
  }, 100);
}

5.2 内存管理

在组件卸载时移除事件监听:

function cleanup() {
  document.querySelector('.buttons').removeEventListener('click', eventHandler);
}

5.3 代码组织结构

calculator/
├── index.html    # 主页面
├── styles.css    # 样式文件
├── script.js    # 主逻辑
│  ├── core.js   # 核心计算逻辑
│  ├── ui.js    # 界面更新
│  └── utils.js   # 工具函数
└── README.md    # 项目说明

六、完整实现代码

6.1 HTML结构

<div class="calculator">
  <div class="display" id="display">0</div>
  <div class="buttons">
    <button class="btn clear" data-value="clear">C</button>
    <button class="btn operator" data-value="+">+</button>
    <button class="btn operator" data-value="-">-</button>
    <button class="btn operator" data-value="*">×</button>
    
    <button class="btn num" data-value="7">7</button>
    <button class="btn num" data-value="8">8</button>
    <button class="btn num" data-value="9">9</button>
    <button class="btn operator" data-value="/">÷</button>
    
    <button class="btn num" data-value="4">4</button>
    <button class="btn num" data-value="5">5</button>
    <button class="btn num" data-value="6">6</button>
    <button class="btn equals" data-value="=">=</button>
    
    <button class="btn num" data-value="1">1</button>
    <button class="btn num" data-value="2">2</button>
    <button class="btn num" data-value="3">3</button>
    <button class="btn num" data-value="0">0</button>
    
    <button class="btn decimal" data-value=".">.</button>
    <button class="btn percent" data-value="%">%</button>
    <button class="btn sign" data-value="+/-">±</button>
  </div>
</div>

6.2 JavaScript核心逻辑

const calculator = {
  displayValue: '0',
  firstOperand: null,
  waitingForSecondOperand: false,
  operator: null,
  
  reset() {
    Object.assign(this, {
      displayValue: '0',
      firstOperand: null,
      waitingForSecondOperand: false,
      operator:
    });
  }
};

function updateDisplay() {
  document.getElementById('display').textContent = calculator.displayValue;
}

function inputDigit(digit) {
  if (calculator.waitingForSecondOperand) {
    calculator.displayValue = digit.toString();
    calculator.waitingForSecondOperand = false;
  } else {
    calculator.displayValue = 
      calculator.displayValue === '0' 
        ? digit.toString() 
        : calculator.displayValue + digit;
  }
}

function handleOperator(nextOperator) {
  const inputValue = parseFloat(calculator.displayValue);
  
  if (calculator.firstOperand === null) {
    calculator.firstOperand = inputValue;
  } else if (calculator.operator) {
    const result = calculate(
      calculator.firstOperand, 
      inputValue, 
      calculator.operator
    );
    calculator.displayValue = String(result);
    calculator.firstOperand = result;
  }
  
  calculator.waitingForSecondOperand = true;
  calculator.operator = nextOperator;
}

function calculate(a, b, op) {
  switch (op) {
    case '+': return a + b;
    case '-': return a - b;
    case '*': return a * b;
    case '/': 
      if (b === 0) {
        alert('错误:除数不能为零');
        return NaN;
      }
      return a / b;
    default: return b;
  }
}

function performCalculation() {
  if (!calculator.operator || calculator.waitingForSecondOperand) return;
  
  const result = calculate(
    calculator.firstOperand,
    parseFloat(calculator.displayValue),
    calculator.operator
  );
  
  calculator.displayValue = String(result);
  calculator.operator = null;
  calculator.firstOperand = result;
  calculator.waitingForSecondOperand = true;
}

// 事件监听
document.querySelector('.buttons').addEventListener('click', (event) => {
  const target = event.target;
  if (!target.matches('button')) return;
  
  const value = target.dataset.value;
  
  if (target.classList.contains('num')) {
    inputDigit(parseInt(value));
  } else if (target.classList.contains('operator')) {
    handleOperator(value);
  } else if (target.classList.contains('equals')) {
    performCalculation();
  } else if (target.classList.contains('clear')) {
    calculator.reset();
  } else if (target.classList.contains('decimal')) {
    if (!calculator.displayValue.includes('.')) {
      calculator.displayValue += '.';
    }
  } else if (target.classList.contains('percent')) {
    const current = parseFloat(calculator.displayValue);
    calculator.displayValue = String(current / 100);
  } else if (target.classList.contains('sign')) {
    const current = parseFloat(calculator.displayValue);
    calculator.displayValue = String(current * -1);
  }
  
  updateDisplay();
});

// 初始化
updateDisplay();

七、测试用例设计

7.1 基本运算测试

测试用例 输入步骤 预期结果
加法运算 5 + 3 = 8
减法运算 10 - 7 = 3
乘法运算 4 * 6 = 24
除法运算 15 / 3 = 5

7.2 连续运算测试

测试用例 输入步骤 预期结果
连续加法 5 + 3 + 2 = 10
混合运算 5 + 3 * 2 = 11
带括号运算 (需扩展实现) -

7.3 边界条件测试

测试用例 输入步骤 预期结果
除零错误 5 / 0 = 错误提示
极大数运算 1E100 * 2 = 2E100
极小数运算 0.0001 * 0.0001 = 1E-8

结论

本文通过系统化的开发流程,实现了包含基本四则运算、异常处理和界面交互的完整计算器应用。核心价值在于展示了如何通过状态管理、事件驱动和模块化设计构建可维护的JavaScript应用。实际开发中可根据需求进一步扩展科学计算、历史记录等功能,但本实现已完整覆盖计算器的基础业务逻辑。

JavaScript 计算器
THE END
战地网
频繁记录吧,生活的本意是开心

相关推荐

JavaScript 中 instanceof 的作用及使用方法详解
在 JavaScript 的类型检查体系中,instanceof 是一个重要的操作符,用于判断一个对象是否属于某个构造函数的实例或其原型链上的类型。本文ZHANID工具网将系统讲解 instanceof...
2025-09-11 编程技术
807

JavaScript出现“undefined is not a function”错误的解决方法
在JavaScript开发中,TypeError: undefined is not a function 是最常见的运行时错误之一,通常表示代码尝试调用一个未定义(undefined)的值作为函数。本文ZHANID工具网将从...
2025-09-10 编程技术
715

基于Python开发一个利率计算器的思路及示例代码
利率计算是金融领域的基础需求,涵盖贷款利息、存款收益、投资回报等场景。传统计算依赖手工公式或Excel表格,存在效率低、易出错等问题。Python凭借其简洁的语法和强大的数学...
2025-09-09 编程技术
801

JavaScript报错“Uncaught ReferenceError”如何解决?
在JavaScript开发中,“Uncaught ReferenceError”是常见且易混淆的错误类型。本文ZHANID工具网从错误本质、常见场景、排查步骤、解决方案四个维度,结合真实代码案例与调试技...
2025-09-09 编程技术
762

JavaScript面试题汇总:高频考点与答案解析
在前端开发领域,JavaScript作为核心语言,其面试题覆盖了从基础语法到高级特性的广泛范围。本文ZHANID工具网将系统梳理JavaScript高频面试考点,结合权威资料与典型案例,为...
2025-09-08 编程技术
675

JavaScript中严格模式(use strict)的作用与使用场景
JavaScript的灵活性既是其优势,也是开发者面临的挑战。非严格模式下,隐式全局变量、模糊的this绑定等特性容易导致难以调试的错误。为解决这些问题,ECMAScript 5(ES5)引入...
2025-09-04 编程技术
653