【JavaScript】FizzBuzz問題を解いてみよう

#今回作ったもの
テキストボックスに入力した整数の倍数をそれぞれ**Fizz**と**Buzz**、公倍数を**FizzBuzz**として1~100の整数を順々に表示させます。
また、テキストボックスに整数値以外(文字列や小数値)が入力された場合は**0以外の整数値を入力してください**と表示されます。
![ezgif-3-4014ad76f55a.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/713434/5b7b3431-2a8c-65d1-2361-204bf0e6e61d.gif)


#コード解説

```index.html
<!DOCTYPE html>
<html lang="ja">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body>
    <h1>FizzBuzz問題</h1>

    <div class="r1">
        <p class="p1">FizzNum:</p>
        <input type="text" value="" id="text1">
    </div>

    <div class="r2">
        <p class="p2">BuzzNum:</p>
        <input type="text" value="" id="text2">
    </div>

    <p><input type="button" value="実行する" onclick="fizzbuzz()"></p>
    <div id="fizzbuzz-result"></div>
    <script>
        function fizzbuzz() {
            const fizzNum = Number(document.getElementById('text1').value);
            const buzzNum = Number(document.getElementById('text2').value);
            const fbArry = [];
            const fbText = [];
            const fbResult = document.getElementById('fizzbuzz-result');

            if(!Number.isInteger(fizzNum) || !Number.isInteger(buzzNum) || fizzNum === 0 || buzzNum === 0) {
                fbResult.textContent = '整数値を入力してください';
                return;
            }

            for(let i = 1; i < 101; i++){
                if(i % fizzNum === 0 && i % buzzNum === 0) {
                    fbArry.push('FizzBuzz' + i);
                } else if(i % fizzNum === 0) {
                    fbArry.push('Fizz' + i);
                } else if(i % buzzNum === 0) {
                    fbArry.push('Buzz' + i);
                } else {
                    fbArry.push(i);
                }
            }

            for(const v of fbArry) {
                fbText.push(`<p>${v}</p>`);
            }

            const fbHTML = fbText.join('');

            fbResult.innerHTML = fbHTML;
        }
    </script>
</body>
</html>
```
まず、htmlでテキストボックスや、**Fizz,Buzz,FizzBuzz**を表示する`div`タグを用意します。
JS本文では、
1. テキストボックスから**fizz**と**buzz**の倍数となる数字を**数値型**で取得する
2. 1.で取得した値が整数値ではなかった場合に**整数値を入力してください**と表示させる処理(※整数値ではなかった場合、関数の処理はそこで終了)
3. 1~100の数値の中で公倍数のものを`FizzBuzz`という文字列とともに、fizzの倍数のものを`Fizz`という文字列とともに、buzzの倍数のものを`Buzz`という文字列とともに`fbArry`に配列として追加
4. 3.の`fbArry`を`<p></p>`タグで囲ったものを配列として`fbText`に追加
5. 4.の`fbText`を`join('')`で**,(カンマ)**を除いた文字列として`fbHTML`に代入
6. 最後に`fbResult.innerHTML = fbHTML`でHTML本文に追加

↑の流れになっています。

#※コード本文追記(修正)

```index.html
<!DOCTYPE html>
<html lang="ja">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body>
    <h1>FizzBuzz問題</h1>

    <div class="r1">
        <p class="p1">FizzNum:</p>
        <input type="text" value="" id="text1">
    </div>

    <div class="r2">
        <p class="p2">BuzzNum:</p>
        <input type="text" value="" id="text2">
    </div>

    <p><input type="button" value="実行する" onclick="fizzbuzz()"></p>
    <div id="fizzbuzz-result"></div>
    <script>
        function fizzbuzz() {
            const fizzNum = Number(document.getElementById('text1').value);
            const buzzNum = Number(document.getElementById('text2').value);
            const fbArry = [];
            const fbResult = document.getElementById('fizzbuzz-result');

            if(!Number.isInteger(fizzNum) || !Number.isInteger(buzzNum) || fizzNum === 0 || buzzNum === 0) {
                fbResult.textContent = '0以外の整数値を入力してください';
                return;
            }

            for(let i = 1; i < 101; i++){
                if(i % fizzNum === 0 && i % buzzNum === 0) {
                    fbArry.push('FizzBuzz' + i);
                } else if(i % fizzNum === 0) {
                    fbArry.push('Fizz' + i);
                } else if(i % buzzNum === 0) {
                    fbArry.push('Buzz' + i);
                } else {
                    fbArry.push(i);
                }
            }

            for(const v of fbArry) {
                const p = document.createElement('p');
                p.textContent = v;
                fbResult.appendChild(p);
            }
        }
    </script>
</body>
</html>
```
後から気づきましたが、最後の`for...of`の中でこう書いた方がすっきりするような気がしたのでこちらも載せておきます。
変更箇所の処理は、

* `for...of`の中で`p`タグを作り、`p`タグそれぞれのテキストに`fbArry`の値を代入して随時`fbResult`に追加する

↑の流れになっています。

**※ただ、コメントで教えていただいた通り、この書き方だとDOMの再レンダリングを繰り返してしまい処理が重くなるようです。お教えくださった方ありがとうございます！**

#コード本文追記(さらに修正)
**コメントで教えていただいたやり方で整数値に0を入力されてもプログラムに異常を起こさずに数値を表示できるコードを書いてみました。**
興味のある方は見てみてください！

```index.html
<!DOCTYPE html>
<html lang="ja">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body>
    <h1>FizzBuzz問題</h1>

    <div class="r1">
        <p class="p1">FizzNum:</p>
        <input type="text" value="" id="text1">
    </div>

    <div class="r2">
        <p class="p2">BuzzNum:</p>
        <input type="text" value="" id="text2">
    </div>

    <p><input type="button" value="実行する" onclick="fizzbuzz()"></p>
    <div id="fizzbuzz-result"></div>
    <script>
        function fizzbuzz() {
            const fizzNum = Number(document.getElementById('text1').value);
            const buzzNum = Number(document.getElementById('text2').value);
            const fbArry = [];
            const fbText = [];
            const fbResult = document.getElementById('fizzbuzz-result');

            if(!Number.isInteger(fizzNum) || !Number.isInteger(buzzNum)) {
                fbResult.textContent = '整数値を入力してください';
                return;
            }

            for(let i = 1; i < 101; i++){
                const fizzCondition = (function() {
                    if(fizzNum === 0) {
                        return i === 0;
                    } else {
                        return i % fizzNum === 0;
                    }
                })();

                const buzzCondition = (function() {
                    if(buzzNum === 0) {
                        return i === 0;
                    } else {
                        return i % buzzNum === 0;
                    }
                })();

                if(fizzCondition && buzzCondition) {
                    fbArry.push('FizzBuzz' + i);
                } else if(fizzCondition) {
                    fbArry.push('Fizz' + i);
                } else if(buzzCondition) {
                    fbArry.push('Buzz' + i);
                } else {
                    fbArry.push(i);
                }
            }

            for(const v of fbArry) {
                fbText.push(`<p>${v}</p>`);
            }

            const fbHTML = fbText.join('');

            fbResult.innerHTML = fbHTML;
        }
    </script>
</body>
</html>
```
お教えくださった方ありがとうございます！
#感想
FizzBuzz問題を解くこと自体はすんなりいきましたが、テキストボックスに整数値以外が入力された時の処理で少し時間がかかりました。
`Number`関数のメソッドは微妙に返す値が違うので気を付けないとですね（笑）