0

0

JS 实现计算器详解及实例代码(一)

高洛峰

高洛峰

发布时间:2017-01-20 17:11:31

|

1300人浏览过

|

来源于php中文网

原创

javascript 实现计算器:

系列文章:

JS 实现计算器详解及实例代码(一)

Javascript 实现计算器时间功能详解及实例(二)

小型JavaScript计算器

自己寻思出的解决方案,比较笨拙的方法,虽然完成了但是还有不少bug,用的方法也不是最有效的,基本功能算是完成了,一些小的细节地方也考虑到了,但是还有其他的细节需要处理。

总体设计思路是,先画草图 -> 设计UI -> 编写UI代码 -> 编写CSS -> 编写JS逻辑代码;

面板(main-board)

面板整体尺寸设计

JS 实现计算器详解及实例代码(一)

标题栏(board-title)

字体: font: 30px/50px “Comic Sans MS”, “微软雅黑”;

宽高:(100%, 50px);

屏显区(board-result)

数字显示区(result-up):

表达式显示区(result-down):

按钮区(board-keys),使用表格完成,然后给每个td添加onclick事件

完成界面

JS 实现计算器详解及实例代码(一)

导入新字体

// main.css
@font-face {
font-family: Lovelo-Black;/×定义font的名字×/
src: url('font/Lovelo Black.otf');/*把下载的字体文件引入进来×/
}

   

代码分析

代码组织结构

计算器对象:Calculator;

计算器属性:

bdResult: 计算器面板上的屏显区DOM对象;

operator:操作符数组,包括'+,-,×,÷,=';

digits:有效数字字符,包括'0-9'和点'.';

dot, equal, zero:'.', ‘=', ‘0'对应三个字符,点,等号,字符'0';

digit:屏显区上层的显示的当前输入的数字;

expression:屏显区下层的显示的输入的数字和操作符组成的表达式;

resSpan:屏显区上层的显示当前数字的span对象;

resDown:屏显区下层的显示表达式的div对象;

last:上一次输入的按钮内容;

allDigits:用表达式解析出来的表达式中所有的有效数字;

ops:用表达式字符串解析出来的表达式中所有的操作符;

hasEqual:判断是否按了'='等号的标识符;

lastRes:上一次计算出来的结果[TODO],尚未用到,待实现可以连续计算;

计算器方法:

init:计算器初始化方法;

addTdClick:给每个td即计算器按钮添加点击事件;

calculatorClickEvent:点击事件;

btnClickHanlder:点击事件处理函数;

showCurrRes:处理屏显区上层和下层将要显示的内容;

showText:将通过showCurrRes处理的结果显示出来;

addZero:对表达式前面加'0'操作;

calResult:计算结果;

clearData:清空数据;

hasOperator:判断表达式中是否有操作符;

isOperator:判断当前字符是否是操作符;

delHeadZero:删除表达式开头的'0';

eSiteGroup站群管理系统1.0.4
eSiteGroup站群管理系统1.0.4

eSiteGroup站群管理系统是基于eFramework低代码开发平台构建,是一款高度灵活、可扩展的智能化站群管理解决方案,全面支持SQL Server、SQLite、MySQL、Oracle等主流数据库,适配企业级高并发、轻量级本地化、云端分布式等多种部署场景。通过可视化建模与模块化设计,系统可实现多站点的快速搭建、跨平台协同管理及数据智能分析,满足政府、企业、教育机构等组织对多站点统一管控的

下载

辅助方法

getResSpan:获取屏显上层的span对象;

$tag:根据标签名去获取标签对象;

$:根据id去获取DOM对象;

代码逻辑

使用方法

引入Calculator.js文件(在编写完UI的基础上)

创建对象并初始化:new Calculator().init();

计算器对象

// 计算器对象
function Calculator() {
 
 // 私有属性
 this.bdResult = $("board-result"); // 计算机面板结果显示区对象
 this.operator = ['+', '-', '×', '÷', '='];
 this.digits = ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '.']; // 组成有效数字的数字数组
 this.dot = '.';
 this.equal = '=';
 this.zero = '0';
 this.digit = "";   // 当前输入的数字
 this.expression = "";   // 表达式
 this.resSpan = getResSpan(); // 数字显示区
 this.resDown = $("result-down"); // 表达式显示区
 this.last = "";   // 上一次按下的按钮内容
 this.allDigits = [];   // 从表达式中获取的所有数字组成的数组,将用来和ops中的操作符对应计算出结果 
 this.ops = [];   // 所有操作符组成的数组
 this.hasEqual = false;  // 判断是否按下了'='键
 this.lastRes = 0;   // 上一次计算的结果,即上一次按等号后计算出的值
 
 
 // 私有方法
 
}

   

添加点击事件(注意this在闭包里的引用问题)

// 为td添加点击事件
Calculator.prototype.addTdClick = function () {
 
 var tds  = $tag("td");
 var that = this; // 需要注意保存this的引用
 // 为每个td添加点击事件
 for (var i = 0; i < tds.length; i++) {
 tds[i].onclick = function (){
  // alert(this.innerText);
  var text = this.innerText;
 
  that.calculatorClickEvent(text);
 };
 }
};

   

计算器点击事件处理入口

// 计算器按钮事件
Calculator.prototype.calculatorClickEvent = function (btnText) {
 
 // 上一个按键是'='
 if (this.hasEqual) {
 this.hasEqual = false;
 this.clearData();
 }
 
 // 结果显示在board-result里
 if (btnText != "AC" && btnText != "CE") {
 this.btnClickHanlder(btnText);
 } else { // AC或CE清零
 this.clearData();
 }
};

   

计算器点击事件处理程序

// 计算器的按键事件处理
Calculator.prototype.btnClickHanlder = function (btnText) {
 
 if ((btnText >= '0' && btnText <= '9') || btnText == this.dot) { // 数字键处理
 
 // 如果上一个是操作符,则清空当前数字区
 if (this.isOperator(this.last)) {
  this.resSpan.innerText = '';
  this.digit = '';
 } else if ((btnText == this.dot) && (this.last == this.dot)) {
  // 如果上一个也是点,则对本次的点按钮不做响应
  return;
 }
 
 this.digit += btnText;
 this.expression += btnText;
 } else if (this.isOperator(btnText)) { // 操作符处理
 
 // 如果当前表达式为'0',按'=',不给响应
 if ((btnText == this.equal) && (this.resDown.innerText == this.zero || this.resDown.innerText == "")) return;
 // 如果上一个是非'='的操作符则不进行处理
 if (!this.isOperator(this.last) && btnText == this.equal) { // '='处理
 
  this.showCurrRes(this.zero, this.expression + btnText); // 计算结果显示在表达式区域
  return;
 } else if (this.isOperator(this.last)) {
  // 上一个是操作符,此次的操作符不做记录
  return;
 } else {
  this.expression += btnText;
 }
 
 }
 
 this.showCurrRes(this.digit, this.expression);
 
 this.last = btnText;
};

   

处理将要显示的表达式和当前输入的数字

// 显示当前结果的触发方法
Calculator.prototype.showCurrRes = function (digit, expression) {
 
 if (!expression) return;
 
 this.showText(digit, expression);
 
 // 1. 没有'=',表示还没有到计算结果的时候,直接退出
 if (expression.indexOf(this.equal) == -1) return;
 
 // 计算出了结果
 this.hasEqual = true;
 
 // 2. 处理只按了数字然后直接按了等号的情况,即:'234='则直接返回234
 var tmpStr = this.delHeadZero(expression.substr(0, expression.length - 1)); // 去掉最后一个'='
 if (!this.hasOperator(tmpStr)) {
 this.showText(tmpStr, expression + tmpStr);
 return;
 }
 
 // 3. 处理表达式字符串,且计算出结果
 var start = 0;
 for (var i = 0; i < expression.length; i++) {
 
 var c = expression[i];
 if (this.isOperator(c)) { // 操作符
  this.ops.push(c); // 保存操作符
  var numStr = expression.substr(start, i + 1); // 数字字符串
  var number = 0;
 
  // 浮点数和整型处理
  if (numStr.indexOf(this.dot)) {
  number = parseFloat(numStr);
  } else {
  number = parseInt(numStr);
  }
  this.allDigits.push(number); // 保存数字
  start = i + 1; // 重设数字起始位置,即操作符的下一个字符开始
 }
 }
 
 // 用allDigits和ops去计算结果
 var res = this.calResult();
 
 // 保存此次计算结果,作为下一次计算用 [TODO]
 this.lastRes = res;
 
 // 将结果显示出来
 this.showText(res + '', expression + res);
};

   

将处理结果显示到屏显区

// 将表达式和计算结果显示到屏显区
Calculator.prototype.showText = function (digitStr, expression) {
 
 // 先删除开头的'0'
 var expStr = this.delHeadZero(expression);
 var digStr = this.delHeadZero(digitStr);
 
 // 然后再根据情况决定是否添加'0'
 var tmp = expression == this.zero ? expression : this.addZero(expStr);;
 var dig = digitStr == this.zero ? digitStr : this.addZero(digStr);
 
 this.resSpan.innerText = dig;
 
 // 如果表达式第一个是操作符,则表示之前按的是'0',则给补上'0',因为前面将开头的'0'都删掉了
 if (this.isOperator(tmp[0])) {
 tmp = this.zero + tmp;
 }
 
 this.resDown.innerText = tmp;
}

   

计算结果函数

// 计算结果
Calculator.prototype.calResult = function () {
 var first = 0;
 var second = 0;
 var res = 0;
 for (var i = 0; i < this.ops.length; i++) {
 first = this.allDigits[i];
 second = this.allDigits[i + 1];
 switch (this.ops[i]) {
  case '+':
  res = first + second;
  break;
  case '-':
  res = first - second;
  break;
  case '×':
  res = first * second;
  break;
  case '÷':
  res = first / second;
  break;
  default:
  break;
 }
 
 this.allDigits[i + 1] = res;
 }
 
 return res;
};

   

清空数据

// 计算完一次,清空所有数据,以备下次计算使用
Calculator.prototype.clearData = function () {
 this.allDigits = [];
 this.ops = [];
 this.expression = this.zero;
 this.digit = '';
 
 this.resSpan.innerText = this.zero;
 this.resDown.innerText = this.zero;
};

   

辅助函数

处理表达式开头的'0'问题(第一个按钮是0键或者第一个是小于1的浮点数,表达式需要补零;)

// 开头添加'0',防止重复出现或者没有'0'情况
Calculator.prototype.addZero = function (expression) {
 
 if (!expression) return this.zero;
 
 if (expression[0] == this.dot) { // 浮点数
 return this.zero + expression;
 } else {
 return expression;
 }
};

   

开头去零函数

// 去开头的零
Calculator.prototype.delHeadZero = function (str) {
 
 // 先把开头的‘0'都删掉
 var tmp = "";
 tmp = str.replace(/^[0]+/gi, "");
 if (tmp[0] == this.dot) { // 浮点数重新补上'0'
 tmp = this.zero + tmp;
 }
 
 return tmp;
};

   

判断字符串里是否含有操作符

// 判断表达式中是否含有操作符
Calculator.prototype.hasOperator = function (str) {
 
 if (!str) return;
 
 for (var i = 0; i < this.operator.length; i++) {
 if (str.indexOf(this.operator[i]) >= 0) {
  return true;
 }
 }
 
 return false;
};

   

其他函数

// 获取输入的数字显示区对象
function getResSpan() {
 return $("result-up").getElementsByTagName("span")[0];
}
 
// 根据标签名获取DOM对象
function $tag(tagName) {
 return document.getElementsByTagName(tagName);
}
 
// 根据ID获取DOM对象
function $(id) {
 return document.getElementById(id);
}

   

问题

文字底部显示:通过设置行高处理;

通过一次性解析表达式需要考虑表达式开头是否需要'0'存在;

感谢阅读,希望能帮助到大家,谢谢大家对本站的支持!

更多JS 实现计算器详解及实例代码(一)相关文章请关注PHP中文网!

热门AI工具

更多
DeepSeek
DeepSeek

幻方量化公司旗下的开源大模型平台

豆包大模型
豆包大模型

字节跳动自主研发的一系列大型语言模型

通义千问
通义千问

阿里巴巴推出的全能AI助手

腾讯元宝
腾讯元宝

腾讯混元平台推出的AI助手

文心一言
文心一言

文心一言是百度开发的AI聊天机器人,通过对话可以生成各种形式的内容。

讯飞写作
讯飞写作

基于讯飞星火大模型的AI写作工具,可以快速生成新闻稿件、品宣文案、工作总结、心得体会等各种文文稿

即梦AI
即梦AI

一站式AI创作平台,免费AI图片和视频生成。

ChatGPT
ChatGPT

最最强大的AI聊天机器人程序,ChatGPT不单是聊天机器人,还能进行撰写邮件、视频脚本、文案、翻译、代码等任务。

相关专题

更多
C++ 设计模式与软件架构
C++ 设计模式与软件架构

本专题深入讲解 C++ 中的常见设计模式与架构优化,包括单例模式、工厂模式、观察者模式、策略模式、命令模式等,结合实际案例展示如何在 C++ 项目中应用这些模式提升代码可维护性与扩展性。通过案例分析,帮助开发者掌握 如何运用设计模式构建高质量的软件架构,提升系统的灵活性与可扩展性。

9

2026.01.30

c++ 字符串格式化
c++ 字符串格式化

本专题整合了c++字符串格式化用法、输出技巧、实践等等内容,阅读专题下面的文章了解更多详细内容。

9

2026.01.30

java 字符串格式化
java 字符串格式化

本专题整合了java如何进行字符串格式化相关教程、使用解析、方法详解等等内容。阅读专题下面的文章了解更多详细教程。

8

2026.01.30

python 字符串格式化
python 字符串格式化

本专题整合了python字符串格式化教程、实践、方法、进阶等等相关内容,阅读专题下面的文章了解更多详细操作。

3

2026.01.30

java入门学习合集
java入门学习合集

本专题整合了java入门学习指南、初学者项目实战、入门到精通等等内容,阅读专题下面的文章了解更多详细学习方法。

20

2026.01.29

java配置环境变量教程合集
java配置环境变量教程合集

本专题整合了java配置环境变量设置、步骤、安装jdk、避免冲突等等相关内容,阅读专题下面的文章了解更多详细操作。

17

2026.01.29

java成品学习网站推荐大全
java成品学习网站推荐大全

本专题整合了java成品网站、在线成品网站源码、源码入口等等相关内容,阅读专题下面的文章了解更多详细推荐内容。

19

2026.01.29

Java字符串处理使用教程合集
Java字符串处理使用教程合集

本专题整合了Java字符串截取、处理、使用、实战等等教程内容,阅读专题下面的文章了解详细操作教程。

3

2026.01.29

Java空对象相关教程合集
Java空对象相关教程合集

本专题整合了Java空对象相关教程,阅读专题下面的文章了解更多详细内容。

6

2026.01.29

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
SciPy 教程
SciPy 教程

共10课时 | 1.3万人学习

R 教程
R 教程

共45课时 | 5.8万人学习

Bootstrap 5教程
Bootstrap 5教程

共46课时 | 3.1万人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号