Webの勉強はじめてみた その8 ～JavaScript編 オブジェクト～

N予備校の「プログラミング入門 Webアプリ」を受講しています。
今回は第一章12節「JavaScriptのオブジェクト」です。

<h2>学んだこと</h2>
:::note
1. オブジェクト内のプロパティは「,」で区切る。
2. 配列みたいに参照できる
3. プロパティの値は省略できる。
:::

<h3>配列みたいに参照できる</h3>
```javascript
var student = {
    name = 'Jake',
    age = 16
}
student['name'];
```

<h3>プロパティの値は省略できる</h3>
```javascript
var age = 13;
var student = {
    name = 'Jake',
    age
}
```

<h2>気を付けたいこと</h2>
:::note
1. メソッドの実行は必ず()をつける
2. 未実装の箇所はコメントで //TODO をつけること 
:::
メソッドは`()`つけるとすぐに実行されるイメージでいいのかな？
下の練習問題では`stop`に`()`をつけないで`onkeydown`プロパティに代入してるので、そういう認識でいます。


<h2>練習問題:時間あてゲーム</h2>
```html
<!DOCTYPE html>
<html lang="ja">
<head>
    <meta charset="UTF-8">
    <title>
        JavaScript のオブジェクト            
    </title>
</head>
<body>
    <h1 id="display-area"></h1>
    <div id="time-area"></div>
    <script src="object.js"></script>
</body>
</html>
```

```javascript
var game ={
    startTime: null,
    displayArea: document.getElementById('display-area'),
    timeArea: document.getElementById('time-area'),
    start: function (){
        //現在時刻を開始時刻として記憶
        startTime = Date.now();
        //キー押下でストップ処理
        document.body.onkeydown = game.stop;  
        //リアルタイム表示
        setInterval(game.displayTime, 50);        
    },
    stop: function (){
        //ストップ時刻を記憶
        var currentTime = Date.now();
        //経過時間取得
        var seconds = (currentTime - startTime) / 1000;
        //結果表示
        var rslt = seconds + "秒でした。";

        if(9.5 <= seconds && seconds <= 10.5){
            game.displayArea.innerText = rslt + "すごい！";
        }else{
            game.displayArea.innerText = rslt + "残念！";
        } 
           
    },
    displayTime: function(){
        //経過時間の表示
        //game.timeArea.innerText = (Date.now() - game.startTime) / 1000;
        game.timeArea.innerText = (Date.now() - startTime) / 1000;
    }
}

//ページ読み込み時に使う処理
var isConfirm = confirm('OKを押して10秒だと思ったら何かキーを押してください');
if(isConfirm){
    //タイマースタート
    game.start();    
}
```

<h3>不明なところ</h3>
:::note warn
同じオブジェクト内のメソッドからプロパティを呼び出す時、オブジェクト名を頭につけると予期しない挙動になった
:::

```javascript
displayTime: function(){
        //経過時間の表示
        console.log(startTime);
        console.log(this.startTime);
        console.log(game.startTime); // nullになる
        //この参照だとnullになってDate.now()の値だけが表示される。
        //game.timeArea.innerText = (Date.now() - game.startTime) / 1000;
        //startTime か this.startTime であれば問題ない 
        game.timeArea.innerText = (Date.now() - startTime) / 1000;
    }
```

どれも`null`になるなら、まだスコープの問題だとかで理解はできそうなんだけれど。
ここがどうもしっくりきてないです。

<h2>まとめ</h2>
不明なところもあるので、ちょっとすっきりしてないですが。
今回で一旦JavaScript編は終了みたいです。
次回はCSS編に突入します。


<h2>追記(2021/12/05)</h2>
`game.startTime`が`null`になる件で、原因が判明したので追記します。

```javascript
    startTime: null,
    displayArea: document.getElementById('display-area'),
    timeArea: document.getElementById('time-area'),

    start: function (){
        //現在時刻を開始時刻として記憶
        //startTime = Date.now();
        game.startTime = Date.now();
        //キー押下でストップ処理
        document.body.onkeydown = game.stop;  
        //リアルタイム表示
        setInterval(game.displayTime, 50);        
    },
```

結論から言えば、
`start`メソッド内の`startTime`がグローバル変数として扱われて(varと同じ扱い)、オブジェクトの`startTime`とは別物になっていたことが原因。

`var`の扱いの厄介さを少し垣間見た気がします。