Javascript计算器等功能失败

时间:2017-12-31 20:56:56

标签: javascript

我使用JavaScript创建了一个计算器。当我将多个数学问题链接在一起时,我得到了我想要的答案,直到我尝试用=按钮获得最终结果。当我只做两个数字时,=按钮完全正常。我设置了我的代码来设置mathHoldOne和mathHoldTwo。两者都包含一个数字和一个布尔值,如果它的设置与否。我已经检查了开发工具,看看两个数字的问题和2+数字的问题之间有什么区别,我似乎无法找到问题。 codepen

const view = {
    //Updates view when buttons are clicked
    updateView: function () {
        let viewScreen = document.getElementsByClassName('js-view')[0];
        let miniView = document.getElementsByClassName('mini-view')[0];
        viewScreen.innerHTML = '';
        miniView.innerHTML = '';
        const jsContainer = document.getElementsByClassName('js-container')[0];
        jsContainer.addEventListener('click', function (e) {
            let show = e.target.innerHTML;
            viewScreen.innerHTML += show;
        });
    },
    //have a handler that sets what each button does with event delegation
    btnHandle: function () {
        let mathType = {"type": undefined};
        let mathHoldOne = {"num": 0, "set": false};
        let mathHoldTwo = {"num": 0, "set": false};
        let btnHandler = document.querySelector('.js-container');

        btnHandler.addEventListener('click', function (event) {
            let btn = event.target;
            let screenValue = document.querySelector('.js-view');
            let miniView = document.querySelector('.mini-view');
            switch (btn.className) {
                //clears whats in the view window
                case('cell clear'):
                    screenValue.innerHTML = '';
                    miniView.innerHTML = '';
                    mathHoldOne.num = 0;
                    mathHoldOne.set = false;
                    mathHoldTwo.num = 0;
                    mathHoldTwo.set = false;
                    mathType.type = undefined;
                    break;
                case('cell math multiply'):
                    //assigns mathHoldTwo.num if mathHoldOne.set is true and blanks the screenValue
                    if (mathHoldOne.set) {
                        mathHoldTwo.num = parseInt(screenValue.innerHTML);
                        mathHoldTwo.set = true;
                        screenValue.innerHTML = '';
                        //if mathHoldOne.set is false it assigns mathHoldOne.num and sets the set property to true
                        //also sets mathType.type to multiply
                    } else {
                        mathHoldOne.num = parseInt(screenValue.innerHTML);
                        mathHoldOne.set = true;
                        screenValue.innerHTML = '';
                        mathType.type = "mulitply";
                    }
                    if (mathHoldOne.set && mathHoldTwo.set) {
                        //if both numbers are set cycle through calcFunc to find which mathType.type matches
                        //and execute that function with the two values
                        for (let name in calcFunc) {
                            if (mathType.type === name) {
                                miniView.innerHTML = calcFunc[name](mathHoldOne.num, mathHoldTwo.num);
                                mathHoldOne.num = calcFunc[name](mathHoldOne.num, mathHoldTwo.num);
                            }
                        }
                        mathHoldTwo.num = 0;
                        mathHoldTwo.set = false;
                        mathType.type = 'multiply';
                    }
                    break;
                case('cell math divide'):
                    if (mathHoldOne.set) {
                        mathHoldTwo.num = parseInt(screenValue.innerHTML);
                        mathHoldTwo.set = true;
                        screenValue.innerHTML = '';
                    } else {
                        mathHoldOne.num = parseInt(screenValue.innerHTML);
                        mathHoldOne.set = true;
                        screenValue.innerHTML = '';
                        mathType.type = "divide";
                    }
                    if (mathHoldOne.set && mathHoldTwo.set) {
                        for (let name in calcFunc) {
                            if (mathType.type === name) {
                                miniView.innerHTML = calcFunc[name](mathHoldOne.num, mathHoldTwo.num);
                                mathHoldOne.num = calcFunc[name](mathHoldOne.num, mathHoldTwo.num);
                            }
                        }
                        mathHoldTwo.num = 0;
                        mathHoldTwo.set = false;
                        mathType.type = 'divide';
                    }
                    break;
                case('cell math add'):
                    if (mathHoldOne.set) {
                        mathHoldTwo.num = parseInt(screenValue.innerHTML);
                        mathHoldTwo.set = true;
                        screenValue.innerHTML = '';
                    } else {
                        mathHoldOne.num = parseInt(screenValue.innerHTML);
                        mathHoldOne.set = true;
                        screenValue.innerHTML = '';
                        mathType.type = "add";
                    }
                    if (mathHoldOne.set && mathHoldTwo.set) {
                        for (let name in calcFunc) {
                            if (mathType.type === name) {
                                miniView.innerHTML = calcFunc[name](mathHoldOne.num, mathHoldTwo.num);
                                mathHoldOne.num = calcFunc[name](mathHoldOne.num, mathHoldTwo.num);
                            }
                        }
                        ;
                        mathHoldTwo.num = 0;
                        mathHoldTwo.set = false;
                        mathType.type = 'add';
                    }
                    break;
                case('cell math subtract'):
                    if (mathHoldOne.set) {
                        mathHoldTwo.num = parseInt(screenValue.innerHTML);
                        mathHoldTwo.set = true;
                        screenValue.innerHTML = '';
                    } else {
                        mathHoldOne.num = parseInt(screenValue.innerHTML);
                        mathHoldOne.set = true;
                        screenValue.innerHTML = '';
                        mathType.type = "subract";
                    }
                    if (mathHoldOne.set && mathHoldTwo.set) {
                        for (let name in calcFunc) {
                            if (mathType.type === name) {
                                miniView.innerHTML = calcFunc[name](mathHoldOne.num, mathHoldTwo.num);
                                mathHoldOne.num = calcFunc[name](mathHoldOne.num, mathHoldTwo.num);
                            }
                        }
                        ;
                        mathHoldTwo.num = 0;
                        mathHoldTwo.set = false;
                        mathType.type = 'subtract';
                    }
                    break;
                case('cell equal'):
                    mathHoldTwo.num = parseInt(screenValue.innerHTML);
                    if (mathType.type === "add") {
                        screenValue.innerHTML = calcFunc.add(mathHoldOne.num, mathHoldTwo.num);
                        miniView.innerHTML = calcFunc.add(mathHoldOne.num, mathHoldTwo.num);
                        mathHoldTwo.num = 0;
                        mathHoldOne.num = 0;
                        mathHoldOne.set = false;
                    } else if (mathType.type === "subract") {
                        screenValue.innerHTML = calcFunc.subtract(mathHoldOne.num, mathHoldTwo.num);
                        miniView.innerHTML = calcFunc.subtract(mathHoldOne.num, mathHoldTwo.num);
                        mathHoldOne.num = (mathHoldOne.num - mathHoldTwo.num);
                        mathHoldTwo.num = 0;
                        mathHoldOne.num = 0;
                        mathHoldOne.set = false;
                    }
                    else if (mathType.type === "mulitply") {
                        screenValue.innerHTML = calcFunc.multiply(mathHoldOne.num, mathHoldTwo.num);
                        miniView.innerHTML = calcFunc.multiply(mathHoldOne.num, mathHoldTwo.num);
                        mathHoldOne.num = (mathHoldOne.num * mathHoldTwo.num);
                        mathHoldTwo.num = 0;
                        mathHoldOne.num = 0;
                        mathHoldOne.set = false;
                    } else if (mathType.type === "divide") {
                        screenValue.innerHTML = calcFunc.divide(mathHoldOne.num, mathHoldTwo.num);
                        miniView.innerHTML = calcFunc.divide(mathHoldOne.num, mathHoldTwo.num);
                        mathHoldOne.num = (mathHoldOne.num / mathHoldTwo.num);
                        mathHoldTwo.num = 0;
                        mathHoldOne.num = 0;
                        mathHoldOne.set = false;
                    }
                    break;
            }
            console.log(mathHoldOne, mathHoldTwo, mathType.type);
        })
    }

};

view.updateView();
view.btnHandle();
const calcFunc = {
    add: function (x, y) {
        return x + y;
    },
    subtract: function (x, y) {
        return x - y;
    },
    multiply: function (x, y) {
        return x * y;
    },
    divide: function (x, y) {
        return x / y;
    },
    clear: function () {
        let view = document.querySelector('js-view');
        view.innerHTML = '';
    }
}

1 个答案:

答案 0 :(得分:0)

虽然它可能无法为您的问题提供单一答案,但我认为我可以提供不同版本的计算器。

这里的主要内容是通过new Function语句解除计算,该语句允许您将字符串作为(一段孤立的)JavaScript代码执行。

单击按钮时会计算出计算结果。因为它不排除给出错误的语句,所以代码放在try / catch块中。在catch块中,您可以向用户指示他输入的计算无效,在当前版本中它只记录错误并返回0.

function executeCalculation( calculation ) {
  var fn = new Function( `return (${calculation});` );
  try {
    return fn();
  } catch (ex) {
    console.log( ex );
    return 0;
  }
}

同时评估完整计算的事实是一个优势,因为order of operators按预期保留。此订单的一个示例是我在评论中留下的一个示例,尝试计算5 + 3 * 5应该导致20,但在您当前的计算中,它将评估为5 + 3 = 8 * 5 = 40

// attach basic event handlers
document
  .querySelectorAll('button')
  .forEach( 
    button => button.addEventListener('click', updateCalculation ) 
  );
  
// some global variables
let currentCalculation = '';
let currentValue = 0;
let memory = 0;
  
// event handler for clicking on the buttons
function updateCalculation( e ) {
  let source = e.target;
  if  (!source) {
    return;
  }
  // use the data-type attribute to check what action needs to be performed
  let type = source.getAttribute('data-type');
  if (!type) {
    return;
  }
  switch (type) {
    case '=':
      currentValue = executeCalculation( currentCalculation );
      currentCalculation = '';
      break;
    case 'clear-view':
      currentCalculation = '';
      break;
    case 'clear-all':
      currentValue = 0;
      currentCalculation = '';
      break;
    case 'store':
      memory = currentValue;
      break;
    case 'retrieve':
      currentCalculation += memory;
      break;
    case 'clear':
      memory = 0;
      break;
    case '*':
    case '+':
    case '-':
    case '/':
      // in case the currentCalculation is empty, it should start with the current value instead
      if (currentCalculation === '') {
        currentCalculation = currentValue;
      }
      currentCalculation += type;
      break;
    default:
      currentCalculation += type;
  }
  // update the screen with the changes
  updateView( currentValue, currentCalculation );
}

function updateView( value, calculation ) {
  document.querySelector('.entry').innerHTML = value;
  document.querySelector('.current-query').innerHTML = calculation;
}

// executes and returns the result of the calculation
function executeCalculation( calculation ) {
  var fn = new Function( `return (${calculation});` );
  try {
    return fn();
  } catch (ex) {
    console.log( ex );
    return 0;
  }
}
.calculator {
  background-color: #000;
  display: inline-block;
}
button {
  margin: 3px;
}
.entry {
  display: block;
  margin: 3px;
  padding: 5px;
  color: #fff;
  text-align: right;
  border: inset #fff 1px;
}
.current-query {
  font-size: 0.7em;
  text-align: right;
  color: #fff;
  height: 20px;
}
.row {
  display: flex;
  flex-flow: row nowrap;
}
.column {
  display: flex;
  flex-flow: column nowrap;
}
<div class="calculator">
<div class="header">
  <div class="view">
    <div class="entry">0</div>
    <div class="current-query"></div>
  </div>
</div>
<div class="quick-buttons">
  <button type="button" data-type="clear-view">CE</button>
  <button type="button" data-type="clear-all">C</button>
  <button type="button" data-type="store">M</button>
  <button type="button" data-type="retrieve">MR</button>
  <button type="button" data-type="clear">MC</button>
</div>
<div class="main-buttons row">
  <div class="numbers column">
    <div class="row">
      <button type="button" data-type="7">7</button>
      <button type="button" data-type="8">8</button>
      <button type="button" data-type="9">9</button>
    </div>
    <div class="row">
      <button type="button" data-type="4">4</button>
      <button type="button" data-type="5">5</button>
      <button type="button" data-type="6">6</button>
    </div>
    <div class="row">
      <button type="button" data-type="1">1</button>
      <button type="button" data-type="2">2</button>
      <button type="button" data-type="3">3</button>
    </div>
    <div class="row">
      <button type="button" data-type="0">0</button>
      <button type="button" data-type=".">.</button>
      <button type="button" data-type="=">=</button>
    </div>
  </div>
  <div class="operations row">
    <div class="column">
      <button type="button" data-type="+">+</button>
      <button type="button" data-type="-">-</button>
      <button type="button" data-type="*">*</button>
      <button type="button" data-type="/">/</button>
    </div>
  </div>
</div>
</div>