3
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

Javascriptで電卓を作ろう 第2回 四則演算をやってみよう。

Last updated at Posted at 2019-05-27

スタイルが出来上がったので、次は計算をしていきたいと思います。
第一回のHTMLとCSSを作る記事は、こちら

目次

第1回 HTMLとCSSでボタンを横並びで配置しよう

  • HTMLのマークアップ
  • CSS

第2回 四則演算をやってみよう(今回の記事はここ)

  • Javascriptで四則演算
  • 6)打った数字をコンソールに出力させよう。
  • 7)打った数字と記号を変数に格納しよう。
  • 8)計算結果を出力させよう。
  • 8-1)「=」を押した時の処理
  • 8-2) 計算結果と計算途中を、計算結果の画面に表示させよう。

第3回 連続で演算記号や小数点が押された場合の不具合処理

  • 最初に「+ ÷ - × =」が押せないようにする。
  • 二回連続で計算できるようにしたい。
  • Cボタン(リセットボタン)を押した時の処理
  • BS(バックスペース)ボタンを使えるようにする

第4回 小数点を正しく入力できるように改善しよう

  • 12.12.や12..12のように小数点を間違って入力できてしまう。
  • 電卓と同じように「.4」と入力したら0.4としたい。

第5回 演算記号を連続して押した時の不具合を直そう

第6回 バックスペースを押した時の不具合を直そう。

第7回 「4 ÷ 3 = 1.33333333333333333」の表示桁数を10桁にしたい

第8回 「電卓と同じ表示画面を目指そう

前回のHTML


<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8">
    <title>電卓</title>
    <link rel="stylesheet" href="style.css">
  </head>
  <body>
    <div class = "container">
<!--      計算結果を出力する場所-->
      <div id = "output_total" class="output ">0</div>
<!--      計算過程を出力する -->
      <div id = "output_sub" class="output active">0</div>
<!--      ボタンを配置する場所-->
      <div class = 'input'>
          <section class = 'row'>
            <div id = "clear">C</div>
            <div class = "num_bth"></div>
            <div class = "num_bth" id="bs">BS</div>       
            <div class = "num_bth " data-index-id= '/'>÷</div>
          </section>
          <section class = 'row'>
            <div class = "num_bth " data-index-id = 9 >9</div>
            <div class = "num_bth " data-index-id = 8 >8</div>
            <div class = "num_bth " data-index-id = 7 >7</div>
            <div class = "num_bth " data-index-id = '*'>×</div>
          </section>
          <section class = 'row'>
            <div class = "num_bth " data-index-id = 6 >6</div>
            <div class = "num_bth " data-index-id = 5 >5</div>
            <div class = "num_bth " data-index-id = 4 >4</div>
            <div class = "num_bth " data-index-id = '-'></div>     
          </section>
          <section class = 'row'>
            <div class = "num_bth " data-index-id = 3 >3</div>
            <div class = "num_bth " data-index-id = 2 >2</div>
            <div class = "num_bth " data-index-id = 1 >1</div>
            <div class = "num_bth " data-index-id = '+'>+</div>
          </section>
          <section class = 'row'>
            <div class = "num_bth" data-index-id = 00 >00</div>
            <div class = "num_bth" data-index-id = 0 >0</div>
            <div class = "num_bth" data-index-id = . >.</div>
            <div id = 'equal_btn'>=</div>       
          </section>        
      </div>
    </div>
    <script src="script.js"></script>
  </body>
</html>

#Javascript処理
6)打った数字をコンソールに出力させよう。
例1)【ボツ】 一応、打った番号は出力されるが、同じコードの繰り返しになる書き方は却下。

'use strict'
{
  const num_bth = document.getElementsByClassName('num_bth');
  num_bth[3].addEventListener('click', () => {
    console.log(num_bth[3].textContent);
  });//9をクリックすると9が出力
  
  num_bth[4].addEventListener('click', () => {
    console.log(num_bth[4].textContent);
  }) ///8をクリックすると9が出力
  
  //以下続く
    
}

これでもコンソールにクリックした数字は出力できますが、こんな書き方をしてたら、先生に怒られてしまいそうです。

例2)【ボツ】同じコードの繰り返しをやめるため、getElementsByClassNameとforを使ってみる

  const num_bth = document.getElementsByClassName('num_bth'); 
    for(let i = 0; i < num_bth.length ; i++) {
      num_bth[i].addEventListener('click', () => {
        console.log(num_bth[i].textContent);
      }) //click
    }//for

これで同じコードを繰り返して書かなくてもクリックしたキーの値をコンソールに出力できました。

例3)【ボツ】もう少し短く書くため、querySelectorAllとforEachを使う

  const num_bth = document.querySelectorAll('.num_bth');
  num_bth.forEach(index => {
    index.addEventListener('click', () => {
      console.log(index.textContent);
    }) //click
  })//forEach
//123456890+-×÷が出力される

数字はうまく出力されますが、この方法だと「÷」を押すとが「÷」出力され、「×」を押すと「×」が出力される。。「/」や「*」が出力されないと計算できない。

ちなみにforEachは配列に対して行うので、複数あるものなら使えるわけではなかった。以下だとエラーになります。

  const num_bth = document.getElementsByClassName('num_bth');
  num_bth.forEach(index => {
    index.addEventListener('click', () => {
      console.log(index.textContent);
    }) //click
  })//forEach
×以下のエラメッセージが表示される
Uncaught TypeError: num_bth.forEach is not a function

例4)【採用】
カスタムdata属性を使う。

忘れてたら、
詳解JavaScript DOM編 #06 カスタムデータ属性を扱ってみよう 参照

  const num_bth = document.querySelectorAll('.num_bth');
  num_bth.forEach(index => {
    index.addEventListener('click', () => {
      console.log(index.dataset.indexId)
    }) //click   
  })//forEach 
//123456890+-*/が出力される
  

7)打った数字と記号を変数に格納しよう。

  const num_bth = document.querySelectorAll('.num_bth');
  let total = 0;//計算式を表す変数 
  num_bth.forEach(index => {
    index.addEventListener('click', () => {
      console.log(index.dataset.indexId)
      total += index.dataset.indexId;  
      console.log(total);  
    }) //click   
  })//forEach

12+3をクリックするとコンソールにこの以下のように出力される。
image.png

【失敗例】

  const num_bth = document.querySelectorAll('.num_bth');
  let total;//計算式を表す変数 
  
  num_bth.forEach(index => {
    index.addEventListener('click', () => {
      console.log(index.dataset.indexId)
        total += index.dataset.indexId;     
      console.log(total);  
    }) //click   
  })//forEach

ボタンを押す前は、変数には数字がないため、undefinedとなってしまう。
image.png

  • 8)計算結果を出力させよう。
    【失敗例】
'use strict'
{
  const num_bth = document.querySelectorAll('.num_bth');
  let total = 0;//計算式を表す変数 
  
//  //数字や記号のボタンを押した時
  num_bth.forEach(index => {
    index.addEventListener('click', () => {
      console.log(index.dataset.indexId)
        total += index.dataset.indexId;     
      console.log(total);  
    }) //click   
  })//forEach
  
  //イコールを押した時
  const equal_btn = document.getElementById('equal_btn');
  equal_btn.addEventListener('click',() =>{
    console.log(eval(total));
  });
  
}

image.png

eval() は文字列として表された JavaScript コードを式として評価する関数。
0が付いていると計算ができない。
最初にクリックした時と、二番目の数字がクリックされた時で処理を変える。
【成功例】

'use strict'
{
  const num_bth = document.querySelectorAll('.num_bth');
  let total = 0;//計算式を表す変数 
  
//  //数字や記号のボタンを押した時
  num_bth.forEach(index => {
    index.addEventListener('click', () => {
      console.log(index.dataset.indexId)
      if(total ===0) {
        total = index.dataset.indexId;  
      }else{
        total += index.dataset.indexId;
      }      
      console.log(total);  
    }) //click   
  })//forEach
  
  //イコールを押した時
  const equal_btn = document.getElementById('equal_btn');
  equal_btn.addEventListener('click',() =>{
    console.log(eval(total));
  });
  
}

12+3=15がコンソールに出力できた。
image.png

8-2) 計算結果と計算途中を、電卓の画面に表示させよう。

'use strict'
{
  const num_bth = document.querySelectorAll('.num_bth');
  let output_sub = document.getElementById('output_sub');//計算結果を表示する場所
  const output_total = document.getElementById('output_total');//計算過程を表示する場所
  let total = 0;//計算式を表す変数 
  
//  //数字や記号のボタンを押した時
  num_bth.forEach(index => {
    index.addEventListener('click', () => {
      console.log(index.dataset.indexId)
      if(total ===0) {
        total = index.dataset.indexId;  
      }else{
        total += index.dataset.indexId;
      }      
      output_sub.textContent = total;
    }) //click   
  })//forEach
  
  //イコールを押した時
  const equal_btn = document.getElementById('equal_btn');
  equal_btn.addEventListener('click',() =>{
    console.log(eval(total));
    output_total.textContent = eval(total);
  });
  
}

image.png
計算結果が出力できた。

#現状の問題点
レベル1はとりあえず計算結果を出力できるまで、ということで、ここまで。

レベル2では、以下の現状の問題点を一つずつ直していきたいと思います。

  • 最初に「+ ÷ - = .」が押せてしまう。
  • 最初に0を連続で押せてしまう。
  • 一度間違えると、全てやり直し(BSボタンを使えるようにしよう)
  • 一度計算をやると、次の計算をするときに、ブラウザを読み込みなおさないといけない(Cボタンを使えるようにしよう)
  • 12.12.や12..12のように小数点を正しくなく入力できてしまう。
  • 割り算等で小数点以下が異様に長い。
  • 記号ボタン(+×÷-)を連続で押せてしまい、計算ができない。(連続で押した場合は、最後に押した記号ボタンが採用されるようにしたい。
  • 電卓と同じように「.4」と入力したら0.4としたい。
3
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?