Javascript 实现计算器:

系列文章:
JS 实现计算器详解及实例代码(一)
Javascript 实现计算器时间功能详解及实例(二)
小型JavaScript计算器
自己寻思出的解决方案,比较笨拙的方法,虽然完成了但是还有不少bug,用的方法也不是最有效的,基本功能算是完成了,一些小的细节地方也考虑到了,但是还有其他的细节需要处理。
总体设计思路是,先画草图 -> 设计UI -> 编写UI代码 -> 编写CSS -> 编写JS逻辑代码;
面板(main-board)
面板整体尺寸设计
标题栏(board-title)
屏显区(board-result)
按钮区(board-keys),使用表格完成,然后给每个td添加onclick事件
完成界面
导入新字体
// main.css
@font-face {
font-family: Lovelo-Black;/×定义font的名字×/
src: url('font/Lovelo Black.otf');/*把下载的字体文件引入进来×/
}
代码分析
代码组织结构
计算器对象:Calculator;
计算器属性:
计算器方法:
辅助方法
代码逻辑
使用方法
计算器对象
// 计算器对象
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);
}
问题
感谢阅读,希望能帮助到大家,谢谢大家对本站的支持!
# Javascript
# 计算器
# 计算器实现代码
# JS
# AngularJS ng-blur 指令详解及简单实例
# 老生常谈onBlur事件与onfocus事件(js)
# jsp+ajax实现的局部刷新较验验证码(onblur事件触发较验)
# javascript委托(Delegate)blur和focus用法实例分析
# Js中的onblur和onfocus事件应用介绍
# AngularJS Controller作用域
# JSP页面跳转方法小结
# 详解js中==与===的区别
# js时间控件只显示年月
# java后端把数据转换为树
# map递归生成json树
# 返回给前端(后台转换)
# 完美解决node.js中使用https请求报CERT_UNTRUSTED的问题
# JS实现iframe自适应高度的方法示例
# Javascript blur与click冲突解决办法
# jsp页面显示数据库的数据信息表
# 第一个
# 清空
# 浮点数
# 按了
# 计算出
# 不做
# 按下
# 补上
# 的是
# 判断是否
# 完成了
# 还没有
# 出了
# 基础上
# 其他的
# 微软
# 希望能
# 然后再
# 不给
# 谢谢大家
相关文章:
完全自定义免费建站平台:主题模板在线生成一站式服务
儿童网站界面设计图片,中国少年儿童教育网站-怎么去注册?
企业微网站怎么做,公司网站和公众号有什么区别?
如何在阿里云虚拟机上搭建网站?步骤解析与避坑指南
如何通过山东自助建站平台快速注册域名?
如何在阿里云高效完成企业建站全流程?
建站之星体验版:智能建站系统+响应式设计,多端适配快速建站
制作网站的模板软件,网站怎么建设?
建站主机功能解析:服务器选择与快速搭建指南
c++怎么用jemalloc c++替换默认内存分配器【性能】
广州美橙建站如何快速搭建多端合一网站?
营销式网站制作方案,销售哪个网站招聘效果最好?
建站之星安全性能如何?防护体系能否抵御黑客入侵?
西安大型网站制作公司,西安招聘网站最好的是哪个?
相亲简历制作网站推荐大全,新相亲大会主持人小萍萍资料?
广东企业建站网站优化与SEO营销核心策略指南
公司网站的制作公司,企业网站制作基本流程有哪些?
成都网站制作报价公司,成都工业用气开户费用?
青岛网站设计制作公司,查询青岛招聘信息的网站有哪些?
建站之星免费模板:自助建站系统与智能响应式一键生成
如何选择可靠的免备案建站服务器?
中山网站推广排名,中山信息港登录入口?
建站主机服务器选购指南:轻量应用与VPS配置解析
动图在线制作网站有哪些,滑动动图图集怎么做?
如何自定义建站之星网站的导航菜单样式?
建站之星图片链接生成指南:自助建站与智能设计教程
广州顶尖建站服务:企业官网建设与SEO优化一体化方案
韩国服务器如何优化跨境访问实现高效连接?
代刷网站制作软件,别人代刷火车票靠谱吗?
建站主机数据库如何配置才能提升网站性能?
建站之星安装路径如何正确选择及配置?
油猴 教程,油猴搜脚本为什么会网页无法显示?
c++怎么编写动态链接库dll_c++ __declspec(dllexport)导出与调用【方法】
如何基于云服务器快速搭建网站及云盘系统?
如何在阿里云ECS服务器部署织梦CMS网站?
已有域名建站全流程解析:网站搭建步骤与建站工具选择
代购小票制作网站有哪些,购物小票的简要说明?
如何在西部数码注册域名并快速搭建网站?
建站之星如何通过成品分离优化网站效率?
如何设置并定期更换建站之星安全管理员密码?
开封网站制作公司,网络用语开封是什么意思?
网站建设制作、微信公众号,公明人民医院怎么在网上预约?
深圳网站制作公司好吗,在深圳找工作哪个网站最好啊?
如何快速选择适合个人网站的云服务器配置?
如何通过网站建站时间优化SEO与用户体验?
,石家庄四十八中学官网?
定制建站流程步骤详解:一站式方案设计与开发指南
如何快速搭建个人网站并优化SEO?
如何在Windows 2008云服务器安全搭建网站?
网站规划与制作是什么,电子商务网站系统规划的内容及步骤是什么?
*请认真填写需求信息,我们会在24小时内与您取得联系。