前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
社区首页 >专栏 >JS实现简易的计算器

JS实现简易的计算器

作者头像
书童小二
发布于 2018-09-03 11:18:26
发布于 2018-09-03 11:18:26
11.2K00
代码可运行
举报
文章被收录于专栏:前端儿前端儿
运行总次数:0
代码可运行

JS可以做的事多了,那就用来实现一个计算器吧

看看手机中的计算器,分为普通计算器和科学计算器

自认脑袋不够大,就实现一个普通版本的吧(支持正负数加减乘除等基本连续的运算,未提供括号功能)

看看图示效果, 或 在线演示

一、知识准备

1+1 = ?

正常来说,我们看到这个表达式都知道怎么运算,知道运算结果

但计算机不一样,计算机无法识别出这串表达式,它只能识别特定的规则:前缀表达式+ 1 1 或后缀表达式1 1 +

举个栗子

(3 + 4) × 5 - 6 就是中缀表达式 - × + 3 4 5 6 前缀表达式 3 4 + 5 × 6 - 后缀表达式

所以为了实现程序的自动运算,我们需要将输入的数据转化为前缀或后缀表达式

前缀、中缀、后缀表达式的概念以及相互转换方法在这里就不多说了,这篇博文 说得比较清楚了 

所以,在这个计算器的实现中,采用了后缀表达式的实现方式,参考以上文章,重点关注这两个算法:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
与转换为前缀表达式相似,遵循以下步骤:
(1) 初始化两个栈:运算符栈S1和储存中间结果的栈S2
(2) 从左至右扫描中缀表达式;
(3) 遇到操作数时,将其压入S2
(4) 遇到运算符时,比较其与S1栈顶运算符的优先级:
(4-1) 如果S1为空,或栈顶运算符为左括号“(”,则直接将此运算符入栈;
(4-2) 否则,若优先级比栈顶运算符的高,也将运算符压入S1(注意转换为前缀表达式时是优先级较高或相同,而这里则不包括相同的情况);
(4-3) 否则,将S1栈顶的运算符弹出并压入到S2中,再次转到(4-1)S1中新的栈顶运算符相比较;
(5) 遇到括号时:
(5-1) 如果是左括号“(”,则直接压入S1
(5-2) 如果是右括号“)”,则依次弹出S1栈顶的运算符,并压入S2,直到遇到左括号为止,此时将这一对括号丢弃;
(6) 重复步骤(2)(5),直到表达式的最右边;
(7)S1中剩余的运算符依次弹出并压入S2
(8) 依次弹出S2中的元素并输出,结果的逆序即为中缀表达式对应的后缀表达式(转换为前缀表达式时不用逆序)。
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
与前缀表达式类似,只是顺序是从左至右:
从左至右扫描表达式,遇到数字时,将数字压入堆栈,遇到运算符时,弹出栈顶的两个数,用运算符对它们做相应的计算(次顶元素 op 栈顶元素),并将结果入栈;重复上述过程直到表达式最右端,最后运算得出的值即为表达式的结果。
例如后缀表达式“3 4 + 5 × 6 -”:
(1) 从左至右扫描,将3和4压入堆栈;
(2) 遇到+运算符,因此弹出434为栈顶元素,3为次顶元素,注意与前缀表达式做比较),计算出3+4的值,得7,再将7入栈;
(3) 将5入栈;
(4) 接下来是×运算符,因此弹出57,计算出7×5=35,将35入栈;
(5) 将6入栈;
(6) 最后是-运算符,计算出35-6的值,即29,由此得出最终结果。

二、实现过程

第一步当然是搭建计算器的页面结构,不是科学计算器,只提供了基本的运算功能,但也能即时地进行运算,显示出完整的中缀表达式,运算后保存上一条运算记录。

要先说一下:本来想实现小数点功能的,但小数点的存在让数据存储与数据显示的实现有了压力,实现过程实在脑大,索性先取消这个功能。

1. 页面结构:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
    <h5>计算计算</h5>
    <!-- 计算器 -->
    <div class="calc-wrap">
        <div class="calc-in-out">
            <!-- 上一条运算记录 -->
            <p class="calc-history" title=""></p>
            <!-- 输入的数据 -->
            <p class="calc-in"></p>
            <!-- 输出的运算结果 -->
            <p class="calc-out active"></p>
        </div>
        <table class="calc-operation">
            <thead></thead>
            <tbody>
                <tr>
                    <td data-ac="cls" class="cls">C</td>
                    <td data-ac="del">&larr;</td>
                    <td data-ac="sq">x<sup>2</sup></td>
                    <td data-ac="mul">&times;</td>
                </tr>
                <tr>
                    <td data-val="7">7</td>
                    <td data-val="8">8</td>
                    <td data-val="9">9</td>
                    <td data-ac="div">&divide;</td>
                </tr>
                <tr>
                    <td data-val="4">4</td>
                    <td data-val="5">5</td>
                    <td data-val="6">6</td>
                    <td data-ac="plus">+</td>
                </tr>
                <tr>
                    <td data-val="1">1</td>
                    <td data-val="2">2</td>
                    <td data-val="3">3</td>
                    <td data-ac="minus">-</td>
                </tr>
                    <td data-ac="per">%</td>
                    <td data-val="0">0</td>
                    <td data-ac="dot">.</td>
                    <td data-ac="eq" class="eq">=</td>
            </tbody>
        </table>
    </div>

2. 结合一点样式:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
body {
    padding: 20px;
    font-family: Arial;
}

.calc-wrap {
    width: 300px;
    border: 1px solid #ddd;
    border-radius: 3px;
}


.calc-operation {
    width: 100%;
    border-collapse: collapse;
}

.calc-in-out {
    width: 100%;
    padding: 10px 20px;
    text-align: right;
    box-sizing: border-box;
    background-color: rgba(250, 250, 250, .9);
}
.calc-in-out p {
    overflow: hidden;
    margin: 5px;
    width: 100%;
}
.calc-history {
    margin-left: -20px;
    font-size: 18px;
    color: #bbb;
    border-bottom: 1px dotted #ddf;
    min-height: 23px;
}

.calc-in,
.calc-out {
    font-size: 20px;
    color: #888;
    line-height: 39px;
    min-height: 39px;
}

.calc-in {
    color: #888;
}
.calc-out {
    color: #ccc;
}

.calc-in.active,
.calc-out.active {
    font-size: 34px;
    color: #666;
}

.calc-operation td {
    padding: 10px;
    width: 25%;
    text-align: center;
    border: 1px solid #ddd;
    font-size: 26px;
    color: #888;
    cursor: pointer;
}

.calc-operation td:active {
    background-color: #ddd;
}

.calc-operation .cls {
    color: #ee8956;
}

这样静态的计算器就粗来了~~

3. JS逻辑

这部分就是重点了,一步步来说

首先是对计算器的监听吧,也就是这个表格,可以使用事件委托的方式,在父级节点上监听处理

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
        // 绑定事件
        bindEvent: function() {
            var that = this;

            that.$operation.on('click', function(e) {
                e = e || window.event;
                var elem = e.target || e.srcElement,
                    val,
                    action;

                if (elem.tagName === 'TD') {
                    val = elem.getAttribute('data-val') || elem.getAttribute('data-ac');    

            ...

监听数据,获取到的只是页面上的某个值/操作符,所以需要将数据存储起来形成中缀,再由中缀转换成后缀,最后通过后缀进行计算

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
        // 中缀表达式
        this.infix = [];
        // 后缀表达式
        this.suffix = [];
        // 后缀表达式运算结果集
        this.result = [];

按照算法步骤,实现出来,这里没有使用到括号,如果实际需要,可在相应位置修改判断条件即可~

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
        // 中缀表达式转后缀
        infix2Suffix: function() {
            var temp = [];
            this.suffix = [];

            for (var i = 0; i < this.infix.length; i++) {
                // 数值,直接压入
                if (!this.isOp(this.infix[i])) {
                    this.suffix.push(this.infix[i]);
                }
                else {
                    if (!temp.length) {
                        temp.push(this.infix[i]);
                    }
                    else {
                        var opTop = temp[temp.length - 1];
                        // 循环判断运算符优先级,将运算符较高的压入后缀表达式
                        if (!this.priorHigher(opTop, this.infix[i])) {
                            while (temp.length && !this.priorHigher(opTop, this.infix[i])) {
                                this.suffix.push(temp.pop());
                                opTop = temp[temp.length - 1];
                            }
                        }
                           // 将当前运算符也压入后缀表达式
                        temp.push(this.infix[i]);
                    }
                }
            }
            // 将剩余运算符号压入
            while (temp.length) {
                this.suffix.push(temp.pop());
            }
        },
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
        // 后缀表达式计算
        calcSuffix: function() {
            this.result = [];

            for (var i = 0; i < this.suffix.length; i++) {
                // 数值,直接压入结果集
                if (!this.isOp(this.suffix[i])) {
                    this.result.push(this.suffix[i]);
                }
                // 运算符,从结果集中取出两项进行运算,并将运算结果置入结果集合
                else {
                    this.result.push(this.opCalc(this.result.pop(), this.suffix[i], this.result.pop()));
                }
            }
            // 此时结果集中只有一个值,即为结果
              return this.result[0];
        }

其实,在实现的时候会发现,中缀、后缀只是一个难点,更复杂的地方是整个计算器的状态变化(或者说是数据变化)

在这个简单的计算器中,就有数字(0-9)、运算符(+ - * /)、操作(清除 删除)、预运算(百分号 平方)、小数点、即时运算等数据及操作

如果是科学计算器那就更复杂了,所以理清如何控制这些东西很关键,而其中最重要的就是中缀表达式的构建与存储

当连续点击+号时,是不符合实际操作的,所以需要一个变量 lastVal 来记录上一个值,随着操作而更新,再通过判断,防止程序出错

在点击=号之后,我们可以继续使用这个结果进行运算,或者重新开始运算

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
    // 构建中缀表达式
        buildInfix: function(val, type) {
            // 直接的点击等于运算之后,
            if (this.calcDone) {
                this.calcDone = false;
                // 再点击数字,则进行新的运算
                if (!this.isOp(val)) {
                    this.resetData();
                }
                // 再点击运算符,则使用当前的结果值继续进行运算
                else {
                    var re = this.result[0];
                    this.resetData();
                    this.infix.push(re);
                }

            }

            var newVal;
             ...

点击删除,是删除一位数,不是直接地删除一个数,然后更新中缀表达式的值

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
            // 删除操作
            if (type === 'del') {
                newVal = this.infix.pop();
                // 删除末尾一位数
                newVal = Math.floor(newVal / 10);
                if (newVal) {
                    this.infix.push(newVal);
                }

                this.lastVal = this.infix[this.infix.length - 1];
                return this.infix;
            }    

而添加操作,要考虑的就更多了,比如连续的连续运算符、连续的数字、运算符+ - 接上数字表示正负数,小数点的连接存取等

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
            // 添加操作,首先得判断运算符是否重复
            else if (type === 'add') {
                // 两个连续的运算符
                if (this.isOp(val) && this.isOp(this.lastVal)) {
                    return this.infix;
                }
                // 两个连续的数字
                else if (!this.isOp(val) && !this.isOp(this.lastVal)) {
                    newVal = this.lastVal * 10 + val;
                    this.infix.pop();
                    this.infix.push(this.lastVal = newVal);

                    return this.infix;
                }
                // 首个数字正负数
                if (!this.isOp(val) && this.infix.length === 1 && (this.lastVal === '+' || this.lastVal === '-')) {
                    newVal = this.lastVal === '+' ? val : 0 - val;
                    this.infix.pop();
                    this.infix.push(this.lastVal = newVal);

                    return this.infix;
                }


                this.infix.push(this.lastVal = val);
                return this.infix;
            }

在很多次操作的时候,计算器都需要即时地进行运算,为简化代码,可以封装成一个方法,在相应的位置调用即可

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
        // 即时得进行运算
        calculate: function(type) {
            this.infix2Suffix();
            var suffixRe = this.calcSuffix();

            if (suffixRe) {
                this.$out.text('=' + suffixRe)
                    .attr('title', suffixRe)
                    .removeClass('active');

                // 如果是直接显示地进行等于运算
                if (type === 'eq') {
                    this.$in.removeClass('active');
                    this.$out.addClass('active');
                    // 设置标记:当前已经显示地进行计算
                    this.calcDone = true;
                    this.lastVal = suffixRe;
                    // 设置历史记录
                    var history = this.infix.join('') + ' = ' + suffixRe;
                    this.$history.text(history).attr('title', history);
                }

            }
        },

剩下的就是点击之后的处理过程了,也就是各种调用处理 传递数据->构建中缀处理数据->中缀转后缀->后缀运算显示

比如点击了数字

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
              // 数字:0-9
                    if (!isNaN(parseInt(val, 10))) {
                        // 构建中缀表达式并显示
                        var infixRe = that.buildInfix(parseInt(val, 10), 'add');
                        that.$in.text(infixRe.join('')).addClass('active');

                        that.calculate();

                        return;
                    }

又比如几个预运算,其实长得也差不多

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
                // 预运算:百分比、小数点、平方
                    else if (['per', 'dot', 'sq'].indexOf(action) !== -1) {
                        if (!that.infix.length || that.isOp(that.lastVal)) {
                            return;
                        }

                        if (action === 'per') {
                            that.lastVal /= 100;
                        } else if (action === 'sq') {
                            that.lastVal *= that.lastVal;
                        } else if (action === 'dot') {
                            // that.curDot = true;
                        }

                        // 重新构建中缀表达式
                        var infixRe = that.buildInfix(that.lastVal, 'change');
                        that.$in.text(infixRe.join('')).addClass('active');

                        that.calculate();
                    }

以上就是这个简单计算器的实现步骤了,变化太多还不敢保证不会出错

基本逻辑如此,如果要加上小数点运算、括号运算、正余弦等科学计算器的功能,还是自己去实现吧。。脑大啊。。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
  1 $(function() {
  2 
  3     function Calculator($dom) {
  4         this.$dom = $($dom);
  5         // 历史运算
  6         this.$history = this.$dom.find('.calc-history');
  7         // 输入区
  8         this.$in = this.$dom.find('.calc-in');
  9         // 输出区
 10         this.$out = this.$dom.find('.calc-out');
 11         this.$operation = this.$dom.find('.calc-operation');
 12 
 13         // 运算符映射
 14         this.op = {
 15             'plus': '+',
 16             'minus': '-',
 17             'mul': '*',
 18             'div': '/'
 19         };
 20         this.opArr = ['+', '-', '*', '/'];
 21 
 22         // 中缀表达式
 23         this.infix = [];
 24         // 后缀表达式
 25         this.suffix = [];
 26         // 后缀表达式运算结果集
 27         this.result = [];
 28         // 存储最近的值
 29         this.lastVal = 0;
 30         // 当前已经计算等于完成
 31         this.calcDone = false;
 32         // 当前正在进行小数点点(.)相关值的修正
 33         this.curDot = false;
 34 
 35         this.init();
 36     }
 37 
 38     Calculator.prototype = {
 39         constructor: Calculator,
 40         // 初始化
 41         init: function() {
 42             this.bindEvent();
 43         },
 44         // 绑定事件
 45         bindEvent: function() {
 46             var that = this;
 47 
 48             that.$operation.on('click', function(e) {
 49                 e = e || window.event;
 50                 var elem = e.target || e.srcElement,
 51                     val,
 52                     action;
 53 
 54                 if (elem.tagName === 'TD') {
 55                     val = elem.getAttribute('data-val') || elem.getAttribute('data-ac');
 56                     // 数字:0-9
 57                     if (!isNaN(parseInt(val, 10))) {
 58                         // 构建中缀表达式并显示
 59                         var infixRe = that.buildInfix(parseInt(val, 10), 'add');
 60                         that.$in.text(infixRe.join('')).addClass('active');
 61 
 62                         that.calculate();
 63 
 64                         return;
 65                     }
 66 
 67                     action = val;
 68 
 69                     // 操作:清除、删除、计算等于
 70                     if (['cls', 'del', 'eq'].indexOf(action) !== -1) {
 71                         if (!that.infix.length) {
 72                             return;
 73                         }
 74 
 75                         // 清空数据
 76                         if (action === 'cls' || (action === 'del' && that.calcDone)) {
 77                             that.$in.text('');
 78                             that.$out.text('');
 79 
 80                             that.resetData();
 81                         }
 82                         // 清除
 83                         else if (action === 'del') {
 84                             // 重新构建中缀表达式
 85                             var infixRe = that.buildInfix(that.op[action], 'del');
 86                             that.$in.text(infixRe.join('')).addClass('active');
 87 
 88                             that.calculate();
 89 
 90                         }
 91                         // 等于
 92                         else if (action === 'eq') {
 93                             that.calculate('eq');
 94 
 95                         }
 96                     }
 97                     // 预运算:百分比、小数点、平方
 98                     else if (['per', 'dot', 'sq'].indexOf(action) !== -1) {
 99                         if (!that.infix.length || that.isOp(that.lastVal)) {
100                             return;
101                         }
102 
103                         if (action === 'per') {
104                             that.lastVal /= 100;
105                         } else if (action === 'sq') {
106                             that.lastVal *= that.lastVal;
107                         } else if (action === 'dot') {
108                             // that.curDot = true;
109                         }
110 
111                         // 重新构建中缀表达式
112                         var infixRe = that.buildInfix(that.lastVal, 'change');
113                         that.$in.text(infixRe.join('')).addClass('active');
114 
115                         that.calculate();
116                     }
117                     // 运算符:+ - * /
118                     else if (that.isOp(that.op[action])) {
119                         if (!that.infix.length && (that.op[action] === '*' || that.op[action] === '/')) {
120                             return;
121                         }
122 
123                         var infixRe = that.buildInfix(that.op[action], 'add');
124                         that.$in.text(infixRe.join('')).addClass('active');
125                     }
126                 }
127             });
128         },
129 
130         resetData: function() {
131             this.infix = [];
132             this.suffix = [];
133             this.result = [];
134             this.lastVal = 0;
135             this.curDot = false;
136         },
137 
138         // 构建中缀表达式
139         buildInfix: function(val, type) {
140             // 直接的点击等于运算之后,
141             if (this.calcDone) {
142                 this.calcDone = false;
143                 // 再点击数字,则进行新的运算
144                 if (!this.isOp(val)) {
145                     this.resetData();
146                 }
147                 // 再点击运算符,则使用当前的结果值继续进行运算
148                 else {
149                     var re = this.result[0];
150                     this.resetData();
151                     this.infix.push(re);
152                 }
153 
154             }
155 
156             var newVal;
157 
158             // 删除操作
159             if (type === 'del') {
160                 newVal = this.infix.pop();
161                 // 删除末尾一位数
162                 newVal = Math.floor(newVal / 10);
163                 if (newVal) {
164                     this.infix.push(newVal);
165                 }
166 
167                 this.lastVal = this.infix[this.infix.length - 1];
168                 return this.infix;
169             }
170             // 添加操作,首先得判断运算符是否重复
171             else if (type === 'add') {
172                 // 两个连续的运算符
173                 if (this.isOp(val) && this.isOp(this.lastVal)) {
174                     return this.infix;
175                 }
176                 // 两个连续的数字
177                 else if (!this.isOp(val) && !this.isOp(this.lastVal)) {
178                     newVal = this.lastVal * 10 + val;
179                     this.infix.pop();
180                     this.infix.push(this.lastVal = newVal);
181 
182                     return this.infix;
183                 }
184                 // 首个数字正负数
185                 if (!this.isOp(val) && this.infix.length === 1 && (this.lastVal === '+' || this.lastVal === '-')) {
186                     newVal = this.lastVal === '+' ? val : 0 - val;
187                     this.infix.pop();
188                     this.infix.push(this.lastVal = newVal);
189 
190                     return this.infix;
191                 }
192 
193             // TODO: 小数点运算
194             //     if (this.isOp(val)) {
195             //         this.curDot = false;
196             //     }
197 
198             //     // 小数点
199             //     if (this.curDot) {
200             //         var dotLen = 0;
201             //         newVal = this.infix.pop();
202             //         dotLen = newVal.toString().split('.');
203             //         dotLen = dotLen[1] ? dotLen[1].length : 0;
204 
205             //         newVal +=  val / Math.pow(10, dotLen + 1);
206             //         // 修正小数点运算精确值
207             //         newVal = parseFloat(newVal.toFixed(dotLen + 1));
208 
209             //         this.infix.push(this.lastVal = newVal);
210             //         return this.infix;
211             //     }
212 
213                 this.infix.push(this.lastVal = val);
214                 return this.infix;
215             }
216 
217             // 更改操作,比如%的预运算
218             else if (type === 'change') {
219                 this.infix.pop();
220                 this.infix.push(this.lastVal = val);
221 
222                 return this.infix;
223             }
224 
225         },
226         // 判断是否为运算符
227         isOp: function(op) {
228             return op && this.opArr.indexOf(op) !== -1;
229         },
230         // 判断运算符优先级
231         priorHigher: function(a, b) {
232             return (a === '+' || a === '-') && (b === '*' || b === '/');
233         },
234         // 进行运算符的运算
235         opCalc: function(b, op, a) {
236             return op === '+'
237                 ? a + b
238                 : op === '-'
239                 ? a - b
240                 : op === '*'
241                 ? a * b
242                 : op === '/'
243                 ? a / b
244                 : 0;
245         },
246         // 即时得进行运算
247         calculate: function(type) {
248             this.infix2Suffix();
249             var suffixRe = this.calcSuffix();
250 
251             if (suffixRe) {
252                 this.$out.text('=' + suffixRe)
253                     .attr('title', suffixRe)
254                     .removeClass('active');
255 
256                 // 如果是直接显示地进行等于运算
257                 if (type === 'eq') {
258                     this.$in.removeClass('active');
259                     this.$out.addClass('active');
260                     // 设置标记:当前已经显示地进行计算
261                     this.calcDone = true;
262                     this.lastVal = suffixRe;
263                     // 设置历史记录
264                     var history = this.infix.join('') + ' = ' + suffixRe;
265                     this.$history.text(history).attr('title', history);
266                 }
267 
268             }
269         },
270 
271         // 中缀表达式转后缀
272         infix2Suffix: function() {
273             var temp = [];
274             this.suffix = [];
275 
276             for (var i = 0; i < this.infix.length; i++) {
277                 // 数值,直接压入
278                 if (!this.isOp(this.infix[i])) {
279                     this.suffix.push(this.infix[i]);
280                 }
281                 else {
282                     if (!temp.length) {
283                         temp.push(this.infix[i]);
284                     }
285                     else {
286                         var opTop = temp[temp.length - 1];
287                         // 循环判断运算符优先级,将运算符较高的压入后缀表达式
288                         if (!this.priorHigher(opTop, this.infix[i])) {
289                             while (temp.length && !this.priorHigher(opTop, this.infix[i])) {
290                                 this.suffix.push(temp.pop());
291                                 opTop = temp[temp.length - 1];
292                             }
293                         }
294                            // 将当前运算符也压入后缀表达式
295                         temp.push(this.infix[i]);
296                     }
297                 }
298             }
299             // 将剩余运算符号压入
300             while (temp.length) {
301                 this.suffix.push(temp.pop());
302             }
303         },
304 
305         // 后缀表达式计算
306         calcSuffix: function() {
307             this.result = [];
308 
309             for (var i = 0; i < this.suffix.length; i++) {
310                 // 数值,直接压入结果集
311                 if (!this.isOp(this.suffix[i])) {
312                     this.result.push(this.suffix[i]);
313                 }
314                 // 运算符,从结果集中取出两项进行运算,并将运算结果置入结果集合
315                 else {
316                     this.result.push(this.opCalc(this.result.pop(), this.suffix[i], this.result.pop()));
317                 }
318             }
319             // 此时结果集中只有一个值,即为结果
320               return this.result[0];
321         }
322     };
323 
324     new Calculator('.calc-wrap');
325 });
本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2016-10-17 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
RxJava系列番外篇:一个RxJava解决复杂业务逻辑的案例
之前写过一系列RxJava1的文章,也承诺过会尽快有RxJava2的介绍。无奈实际项目中还未真正的使用RxJava2,不敢妄动笔墨。所以这次还是给大家分享一个使用RxJava1解决问题的案例,希望对大家在使用RxJava的时候有一点点启发。对RxJava还不了解的同学可以先去看看我之前的RxJava系列文章: RxJava系列1(简介) RxJava系列2(基本概念及使用介绍) RxJava系列3(转换操作符) RxJava系列4(过滤操作符) RxJava系列5(组合操作符) RxJava系列6(从
张磊BARON
2018/04/13
1.4K0
RxJava系列番外篇:一个RxJava解决复杂业务逻辑的案例
RxJava(三) flatMap 操作符用法详解
还是以上一篇map操作符的例子吧,如果对 map操作符 不是很了解的,可以看看我之前的文章。
全栈程序员站长
2022/09/05
1.8K0
RxJava从入门到不离不弃(一)——基本概念和使用
RxJava的编程思想已经在Android开发者中变得越来越流行。有个不好的点就是上手不太容易,尤其是大部分人之前都是使用命令式编程语言。
蜻蜓队长
2018/08/03
7920
RxJava从入门到不离不弃(一)——基本概念和使用
【译】对RxJava中-repeatWhen()和-retryWhen()操作符的思考
第一次见到.repeatWhen()和.retryWhen()这两个操作符的时候就非常困惑了。不得不说,它们绝对是“最令人困惑弹珠图”的有力角逐者。
用户1740424
2018/07/23
2.1K0
【译】对RxJava中-repeatWhen()和-retryWhen()操作符的思考
【译】使用RxJava代替EventBus类库
如今的Android社区,人人都在讨论RxJava以及为什么我们应该在项目中使用RxJava。当我们开始在Android项目中使用RxJava的时候,就已经意识到了,我们的代码库可以不再需要Otto了(或其他事件总线类库)。
用户1740424
2018/07/23
4430
【译】使用RxJava代替EventBus类库
【译】RxJava变换操作符:-concatMap(-)与-flatMap(-)的比较
是时候回归写作了。(译者注:原作者吧啦吧啦唠家常,这里就不做翻译了,但是,有两个重要的链接,点我,再点我)
用户1740424
2018/07/23
8240
【译】RxJava变换操作符:-concatMap(-)与-flatMap(-)的比较
RxAndroid从零开始学之五(常见操作符与三级缓存)
RxAndroid的操作符有很多,本以为写了上一节的一些基本的Operator就可以正常编写代码了,但是后来在github上看googlesample,发现了一些另外的Operator。那么本文就继续介绍这些operator并加上自己的一些理解。
Frank909
2019/01/14
6350
【译】使用RxJava实现延迟订阅
我越来越喜欢把RxJava的defer()操作符作为一个工具来使用,以确保Observable代码在被订阅后才执行(而不是创建后立即执行)。我之前写过一些有关defer()的代码,但是,现在我想做更详细的描述。
用户1740424
2018/07/23
8390
【译】使用RxJava实现延迟订阅
【译】避免打断链式结构:使用.compose( )操作符
*[Chains break by the weakest link](https://www.flickr.com/photos/hernanpc/7115374283)*
小鄧子
2018/08/20
6610
RxJava简析
rxjava文档地址https://mcxiaoke.gitbooks.io/rxdocs/content/ 这个是中文版的
用户3112896
2020/11/25
7350
Android RxJava 实战系列:从磁盘 / 内存缓存中 获取缓存数据
Carson_Ho的Github地址 = RxJava2实战系列:从磁盘 / 内存缓存中 获取缓存数据
Carson.Ho
2019/02/22
2K0
Android应用架构
来源: 小鄧子(@Rx小鄧子) Android开发生态圈的节奏非常之快。每周都会有新的工具诞生,类库的更新,博客的发表以及技术探讨。如果你外出度假一个月,当你回来的时候可能已经发布了新版本的Support Library或者Play Services 我与Ribot Team一起做Android应用已经超过三年了。这段时间,我们所构建的Android应用架构和技术也在不断地演变。本文将向您阐述我们的经验,错误以及架构变化背后的原因。 曾经的架构 追溯到2012年我们的代码库使用的是基本结构,那个时候我们没有
编程范 源代码公司
2018/04/16
1.3K0
Android应用架构
【译】RxJava中的事件广播
如果你想多点传播一个事件,也就是向所有的下游操作符或订阅者发送同一个事件。这在做耗时操作如网络请求等场景来讲是非常有用的。你不需要为每个订阅者做重复的网络请求,只需执行一次,然后传播响应结果即可。
用户1740424
2018/07/23
8270
【译】RxJava中的事件广播
RxJava三问—基础知识点回顾
然后开始提问题了,Rxjava涉及的内容很多,我还是会以三个问题为单位,从易到难,一篇篇的说下去,今天的三问是:
码上积木
2020/12/11
6280
Android RxJava应用:合并数据源
Rxjava由于其基于事件流的链式调用、逻辑简洁 & 使用简单的特点,深受各大 Android开发者的欢迎。
Carson.Ho
2022/03/25
7940
Android RxJava应用:合并数据源
大佬们,一波RxJava 3.0来袭,请做好准备~
每个Android开发者,都是爱RxJava的,简洁线程切换和多网络请求合并,再配合Retrofit,简直是APP开发的福音。不知不觉,RxJava一路走来,已经更新到第三大版本了。不像RxJava 2对RxJava 1那么残忍,RxJava 3对RxJava 2的兼容性还是挺好的,目前并没有做出很大的更改。RxJava2到2020年12月31号不再提供支持,错误时同时在2.x和3.x修复,但新功能只会在3.x上添加。
Rouse
2019/07/17
1.9K0
大佬们,一波RxJava 3.0来袭,请做好准备~
一篇博客让你了解RxJava
RxJava可以说是2016年最流行的项目之一了,最近也接触了一下RxJava,于是想写一篇博客,希望能通过这篇博客让大家能对其进行了解,本篇博客是基于RxJava2.0,跟RxJava1.0还是有很多不同的
老马的编程之旅
2022/06/22
5440
一篇博客让你了解RxJava
【译】RxJava中的事件广播
如果你想多点传播一个事件,也就是向所有的下游操作符或订阅者发送同一个事件。这在做耗时操作如网络请求等场景来讲是非常有用的。你不需要为每个订阅者做重复的网络请求,只需执行一次,然后传播响应结果即可。
小鄧子
2018/08/20
5980
【译】RxJava中的事件广播
Android RxJava 实战讲解:合并数据源 & 同时展示数据
前言 Rxjava,由于其基于事件流的链式调用、逻辑简洁 & 使用简单的特点,深受各大 Android开发者的欢迎。 如果还不了解RxJava,请看文章:Android:这是一篇 清晰 & 易懂的R
Carson.Ho
2019/02/22
3.6K2
RxJava 2.0还没熟悉,RxJava 3.0说来就来了!(多种操作符代码详解篇)
在上篇文章中讲的是关于Rxjava的基础篇,今天来讲讲多种操作符的具体内容,操作符太多了,大家准备好啊,耐心看~
Android技术干货分享
2019/07/19
2.2K0
RxJava 2.0还没熟悉,RxJava 3.0说来就来了!(多种操作符代码详解篇)
推荐阅读
相关推荐
RxJava系列番外篇:一个RxJava解决复杂业务逻辑的案例
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档