質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

87.61%

[jQuery]onイベント内での読み込みの順番について

解決済

回答 2

投稿 編集

  • 評価
  • クリップ 1
  • VIEW 774

score 78

こんにちは。表題のonイベントで挙動があまりよくわからないところがあるので質問させていただきます。

現在下記の様な処理をしているのですが、console.logのところでsetA後の値が出力されてしまいます。(下の例ではsetA前の値が出力されます)。
実際のsetAに該当する部分には特に非同期処理等は含まれていないので、クリックイベントが発生した時には素直に上から読み込まれると思っていたのですが、何を見落としているか分からないので、ご教授頂けたら幸いです。
元のファイルはこちらで確認できますが、ちょっと長いので下の様に簡素にしました。

元の例を見ないともちろん確定はできないと思うのですが、時間もかかりますのでもし下の例からだけでお分かりになることがあれば教えてください。

よろしくお願いします。

let a = 1;
let b = 2;

$('#id').on('click', function(){
                    console.log(a);
                    const c = $(this).index();
                    setA(b, c);
                 });

function setA(b,c){
   a = b + c;
}

追記

単純化させたコードを載せて逆に混乱させてしまった様なので、少々長いですが、コード全文載せます。
onイベントの中のplacePieceというメソッドはboardという変数に新たな値を代入するメソッドなので、console.log(board)(*1)では変更前のboardを表示して、console.log(board)(*2)では変更後の値が表示されることを期待していたのですが、どちらも変更後(つまりplacePieceメソッドが動作した後)の値を表示しています。

placePiece自体が期待した動作をしていないので、読み込みの順番がおかしいのは何となく分かっているのですが、どこが間違っているのか分からないので質問させていただきました。

boardという変数に新たな値を代入する直前でconsole.logしても新しい値の代入後のboardが表示されるので、混乱しています。

<!DOCTYPE html>
<html lang="en" dir="ltr">
    <head>
        <meta charset="utf-8">
        <title></title>
        <style>
            #reversiTable {
                border: 2px solid black;
                background: #2A2;
            }
            #reversiTable td {
                border: 2px solid black;
                width: 100px;
                height: 100px;
            }
            .blackPiece{
                width: 70px;
                height: 70px;
                background: black;
                border-radius: 50%;
                margin: auto;
            }
            .whitePiece{
                width: 70px;
                height: 70px;
                background: white;
                border-radius: 50%;
                margin: auto;

            }
        </style>
    </head>
    <body>
        <div>
            <table id="reversiTable">

            </table>
        </div>

        <div id="id">
        </div>

        <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
        <script type="text/javascript">
            (function(){
                // set borad
                let table = document.getElementById("reversiTable");
                for (let i = 0; i < 8; i++) {
                    let tr = document.createElement('tr');
                    table.appendChild(tr);
                }

                let trElem = table.children;
                for (let i = 0; i < 8; i++) {
                    for (var j = 0; j < 8; j++) {
                        let td = document.createElement('td');
                        trElem[i].appendChild(td)
                    }
                }

                tds = $('td');
                for (var i = 0; i < tds.length; i++) {
                    tds.eq(i).attr('value', i);
                    tds.eq(i).attr('class', 'tdElements');
                    tds.eq(i).attr('id', 'tdId-' + i);
                    tds.eq(i).append("<div></div>")
                }



                // initialize reversi pieces
                let serializedBoard = [];
                let board = [];
                let activePlayer = 1;

                for (var i = 0; i < 64; i++) {
                    serializedBoard.push(0);
                }

                serializedBoard[27] = 2;
                serializedBoard[28] = 1;
                serializedBoard[35] = 1;
                serializedBoard[36] = 2;

                for (var i = 0; i < 8; i++) {
                    let array = [];
                    for (var j = 0; j < 8; j++) {
                        array.push(serializedBoard[8*i + j]);
                    }
                    board.push(array);
                }

                for (var i = 0; i < serializedBoard.length; i++) {
                    if (serializedBoard[i] === 1){
                        $("#tdId-"+i+" > div").addClass('whitePiece');
                    } else if (serializedBoard[i] === 2){
                        $("#tdId-"+i+" > div").addClass('blackPiece');
                    }
                }

                for (var i = 0; i < serializedBoard.length; i++) {
                    const x = i % 8;
                    const y = Math.floor(i / 8);
                    board[y][x] = serializedBoard[i]
                }


                //
                // functions of reversi
                //

                $('td').on('click', function(){

                    console.log(board); // *1

                    // クリック箇所の取得
                    const posX = $(this).index();
                    const posY = $(this).parent().index();

                    // 石をひっくり返すメソッド
                    placePiece(posX, posY, activePlayer);

                    // 盤面の状態を2次元配列から1次元配列にするメソッド
                    serializeTheBoard();

                    // 盤面の状態を表す配列から石が置いてある場所にCSSを適用するメソッド
                    setColorOfPieces();

                    console.log(board); // *2

                  });

                 function placePiece(_posX, _posY, _activePlayer){
                     let opponent = getOpponent(_activePlayer);
                     if (board[_posY][_posX] === 0){
                         turnOverPiece(_posY, _posX, opponent);
                         switchActivePlayer(_posY, _posX, _activePlayer);

                     }else{
                         return;
                     }
                 }

                 function getOpponent(_activePlayer) {
                     if (_activePlayer === 1){
                         return 2;
                     }else{
                         return 1;
                     }
                 }

                 function switchActivePlayer(_posX, _posY, _activePlayer){
                     if (board[_posY][_posX] === activePlayer){
                         if (activePlayer === 1) {
                             activePlayer = 2;
                         }else{
                             activePlayer = 1;
                         }
                     }
                 }

                 function turnOverPiece(posY, posX, opponent){
                     for (var i = -1; i <= 1; i++) {
                         for (var j = -1; j <= 1; j++) {
                             if (board[posY+j][posX+i] == opponent){
                                 flipPieces(posY, posX, j, i, opponent);
                             }
                         }
                     }
                 }


                 function flipPieces(posY, posX, j, i, opponent){
                     let counter = 1;
                     let initDiffX = i;
                     let initDiffY = j;
                     do {
                         counter++;
                         diffX = initDiffX * counter;
                         diffY = initDiffY * counter;

                         if (board[posY + diffY][posX + diffX] === 0){
                             break;
                         }else if (board[posY + diffY][posX + diffX] === activePlayer){
                             for (var a = 1; a < counter; a++){
                                 board[posY + (a * j)][posX + (a * i)] = activePlayer;
                             }
                             board[posY][posX] = activePlayer;
                         }

                     } while (board[posY + diffY][posX + diffX] == opponent);
                 }


                 function serializeTheBoard(){
                     for (var i = 0; i < serializedBoard.length; i++) {
                         const x = i % 8;
                         const y = Math.floor(i / 8);
                         serializedBoard[i] = board[y][x];
                     }
                 }

                 function setColorOfPieces(){
                     for (var i = 0; i < serializedBoard.length; i++) {
                         if (serializedBoard[i] === 1){
                             $("#tdId-"+i+" > div").addClass('whitePiece');
                         } else if (serializedBoard[i] === 2){
                             $("#tdId-"+i+" > div").addClass('blackPiece');
                         }
                     }
                 }





            })();


        </script>
    </body>
</html>
  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 過去に投稿した質問と同じ内容の質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

質問への追記・修正、ベストアンサー選択の依頼

  • maisumakun

    2019/04/05 07:40

    最低限、その現象が再現する例を出してください。書かれたコードで再現しないということは、今書かれている枠組みには「問題がない」ということを示していることになります。

    キャンセル

  • dounatsu

    2019/04/05 07:50

    ご指摘の件はごもっともなのですが、色々試しても再現できなかったので、簡略化したコードと実際に問題の出ているコードのリンクを貼らさせて頂きました。もし読み込みの部分で何か知見を頂けたらと思い、投稿させていただきました。

    キャンセル

  • m.ts10806

    2019/04/05 08:17

    書いたようにしか動かないのがプログラムですが、それを動作させて確認しているのは人間なので「実は気のせいだった」ということはなくはないです。色々試して再現できなかったのであれば、いったん置いておき、進まれてはどうでしょうか。

    キャンセル

  • moredeep

    2019/04/05 09:31

    「実は気のせいだった」に1票ですが、少なくとも、「コードの"どの箇所"で"どの値"が"どうなっていなければいけない"が、実際は"どうなっている"ためにおかしいと判断している」くらいは書かないと何が聞きたいかわからないです。
    現状ではflipPiecesはバグってますね。くらいしか・・・

    キャンセル

回答 2

checkベストアンサー

+1

console.log(board)で表示されるのは配列なのですが、開発者コンソール上では配列内のその値の評価まではやっていないようですね。
以下のように表示すればわかるかと思います。

var values = "";
for(var i = 0; i < board.length; i++) {
  for(var j = 0; j < board[i].length; j++) {
    values += board[i][j] + ","
  }
  values += "\n";
}
console.log(values)

コメントを受け追記

イベント云々ではなくconsole.logか開発者コンソールの仕様だと思います。例えば下記を実行した場合、setTimeoutの中の処理が実行される前(10秒以内)に中身を確認すると先二つの値は[1,0]となっています。
しかしsetTimeoutの中の処理が実行された後に(10秒以上後)に"初めて"中身を確認すると、3つとも[1,1]になっています。(chromeで確認)

var test = [[0,0,0]];
console.log(test);
test[0][0] = 1;
console.log(test);
setTimeout(function(){
    test[0][1] = 1;
    console.log(test);
}, 10000);


何かの仕様でこうなっているというような記述を見つけることが出来ませんでしたが、こうしないと巨大なデータをログ出力したらしょっちゅう固まるでしょうし、妥当なんじゃないかなと思います。

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2019/04/05 10:36

    配列の中身の評価は後回しにされるということでしょうか?つまり、今回の場合は8*8の配列だけ準備しておいて、その中身はクリックイベントの最後に入れられるといった感じでしょうか?

    キャンセル

  • 2019/04/05 12:03

    回答に追記しましたが、cosole.log(XXX)はあくまでもXXXのプロパティを表示してくれるものなんだと思います。XXXのプロパティがObject(or Array)の場合、さらに展開して中身を見せてくれるお役立ち機能はあるが、その展開した値は、展開したその瞬間の値であるという感じなんだと思います。

    キャンセル

  • 2019/04/05 16:16

    ありがとうございます。理解できました。

    キャンセル

0

 $(this).index();

が何をしたいのかわかりませんが、普通に上から処理されてますけど

<script>
$(function(){
  let a = 1;
  let b = 2;
  $('#id').on('click', function(){
    console.log(a);
    //const c = $(this).index();
    const c = 3;
    setA(b, c);
  });
});
function setA(b,c){
   a = b + c;
}
</script>
<input type="button" id="id" value="hoge">

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

15分調べてもわからないことは、teratailで質問しよう!

  • ただいまの回答率 87.61%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

同じタグがついた質問を見る