2017-12-31 191 views
-1

JavaScriptを使用して電卓を作成しました。私が複数の数学問題を連鎖させるとき、私は試して=ボタンで最終結果を得るまで私が望む答えを得ます。私は2つの数字だけを行うと、ボタンは完全にうまく動作します。私はmathHoldOneとmathHoldTwoを設定するように自分のコードを設定しました。両方とも数値とブール値を含んでいます。私は、2つの数字の問題と2つ以上の数字の問題の違いはdevのツールを調べたところ、問題は見つからないようです。 codepenJavascript calculator equal function fails

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

これまでの基本的な計算の問題のために '' eval'または新しいFunction'を使用するのではないでしょうか?私はあなたもmultiply関数に問題があると思います( 'case( 'cell equal')'文のif文で記述されていないようです)。私はあなたのコードがあまりにも複雑であると信じています(例えば、この 'if(mathHoldOne.set && mathHoldTwo.set)'を呼び出すすべてのケースブロックでは、あなたはそれを幾分動的に評価します) 5 + 3 * 5'は '20'ですが、文章を一度に実行すると' 40'と評価されます – Icepickle

答えて

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 * 520になるはずですが、現在の計算では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>