JavaScriptのクラスを学ぶ演習・課題

# 本記事の目的
- クラスの定義ができるようになること。
- クラスに関数を作れるようになること。
- コンストラクタを作れるようになること。

# 前提
JavaScriptの実行環境を作ることができる。
関数使える

# 演習1 Loggerクラスを生成する。
クラスとは何か？とかの説明は理解しづらいのでさくっと動くものを作っていく。

まず以下のようにhtmlを作る

```index.html
<!DOCTYPE html>
<html lang='en'>
<head>
    <meta charset='UTF-8'>
    <meta name='viewport' content='width=device-width, initial-scale=1.0'>
    <script type="text/javascript" src='./main.js' defer></script>
    <title>Document</title>
</head>
<body>
    <div class="canvas"></div>
</body>
</html>
```

同階層に`main.js`を作成し、以下のように記述


```main.js
// Loggerというclassを定義
class Logger {

    logHelloWorld(){
        console.log("Hello World");
    }
}

// Loggerを生成 (生成したもの,ここではloggerをインスタンスという)
const logger = new Logger();
// LoggerのlogHelloWorldクラスを実行する。
logger.logHelloWorld();
```

そして、index.htmlを開くと以下のようにconsoleにHello Worldと表示される

![スクリーンショット 2020-08-29 21.15.00.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/113504/8d52d073-44ec-af0c-2d51-195fba4a1660.png)

順を追って説明していく。

クラスを使うステップは「クラスの定義」と「クラスの実体の生成 (インスタンス化)」の2つ。

まずはクラスを定義する。

```main.js
class Logger {

    logHelloWorld(){
        console.log("Hello World");
    }
}
```
ここではLoggerというクラスを定義している。

```.js:クラスの定義の構文
class クラス名 {
    関数名(){
        関数の中身
    }
}
```

クラスの関数は通常の関数の作り方と異なっていることに注意。

![スクリーンショット 2020-08-29 21.20.43-1.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/113504/09547cf4-83dc-58f0-e5ac-c2c92839a00a.jpeg)

次にクラスの実体の生成 <= これをインスタンス化という。
実体のことをインスタンスという。

```main.js
const logger = new Logger();
```

```.js:インスタンス化の構文
const クラスのインスタンス = new クラス名();
```

![スクリーンショット 2020-08-29 21.32.16.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/113504/a8763d22-a633-796e-7b5b-cf37f2b91f39.jpeg)


あとはそのインスタンスの関数を呼ぶ

```main.js
logger.logHelloWorld();
```

# 演習2 コンストラクタ
コンストラクタはnewしたときに呼ばれる処理のこと。
コンストラクタの例を以下に示す。

```main.js
class Logger {
    // コンストラクタ
    constructor(){
        this.lastLogContent = "";
    }

    logHelloWorld(){
        const content = "Hello World";
        console.log(content);
        this.lastLogContent = content;
    }

    // 返り値のある関数の書き方
    getLastLogContent(){
        return this.lastLogContent;
    }
}

const logger = new Logger();
logger.logHelloWorld();
const lastLog = logger.getLastLogContent();
console.log("最後のログの内容は" + lastLog);
```

![スクリーンショット 2020-08-29 22.47.56.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/113504/cbd03085-6bee-86f5-4f50-d119f334adc2.png)

コンストラクタの構文

```.js
class クラス名 {
    constructor(){
        newしたときに呼び出す処理
    }
}
```

ここでは

```main.js
class Logger {
    // コンストラクタ
    constructor(){
        this.lastLogContent = "";
    }
```

と書くことによってLoggerの中に`lastLogContent`という「メンバ変数」を定義し、初期値に空文字をいれている。

> メンバ変数はクラスの中の変数みたいな意味

メンバ変数をつかうことによってインスタンスが状態を持てるようになる。

メンバ変数の頭には`this.`をつける。
「このクラスのlastLogContent」と示すため。

```.js
    logHelloWorld(){
        const content = "Hello World";
        console.log(content);
        this.lastLogContent = content; // <- ここでログの内容を保存し
    }

    // 返り値のある関数の書き方
    getLastLogContent(){
        return this.lastLogContent; // <- あとで取り出せるようにしておいている
    }
```

なお、引数のある関数は以下の用に作る

```main.js
class Logger {
    constructor(){
        this.lastLogContent = "";
    }

    logHelloWorld(){
        const content = "Hello World";
        this.log(content); // <- 変更
    }
    
    // 追加
    log(content){
        console.log(content);
        this.lastLogContent = content;
    }

    getLastLogContent(){
        return this.lastLogContent;
    }
}
```

![スクリーンショット 2020-08-29 23.00.25.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/113504/e0017d04-c805-bc93-ea59-05722e678392.png)

# 課題1 クラスを作ってみる

![スクリーンショット 2020-08-29 23.03.19.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/113504/e9ac2f63-c8d5-0336-2a55-5c1e87df2098.png)

図のようなクラスを作成し、sumに適当な値を渡して結果をconsoleに表示せよ。

なお、sumの関数が返すのはaとbの和とする。

# 演習3 コンストラクタに引数を渡す。

モンスタークラスを作ってみる。

![スクリーンショット 2020-08-29 23.16.15.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/113504/6cdaf038-75c9-d6c4-93a9-2ba86ebce8f6.png)

```main.js
class Monster {
    constructor(name, hp, attack){
        this.name = name;
        this.hp = hp;
        this.attack = attack;
    }
}

const slime = new Monster("スライム", 10, 5);
console.log(slime.name + "のhpは" + slime.hp);
```

![スクリーンショット 2020-08-29 23.15.50.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/113504/00592c7a-6e19-6733-c262-6546c9cd87cf.png)

演習2ではメンバ変数の`lastLogContent`を`getLastLogContent`関数経由でとってきたが、「.」で繋げるだけでも取ってこれる。

# 演習4 1つのクラスから複数のインスタンスを作る。

![スクリーンショット 2020-08-29 23.34.20.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/113504/a19f7f36-7301-9940-3b31-16a3af5e67b6.png)


```Monster.js
class Monster {
    constructor(name, hp, attack){
        this.name = name;
        this.hp = hp;
        this.attack = attack;
    }

    damage(value){
        this.hp -= value;
        if (this.hp <= 0)
        {
            this.hp = 0;
        }
    }

    logState(){
        if(this.hp > 0)
        {
            console.log(this.name + "のhpは" + this.hp);
        }else{
            console.log(this.name + "は倒れている");
        }
    }
}

console.log("スライムがあらわれた");
const slime = new Monster("スライム", 10, 5);
slime.logState();
console.log("ドラゴンがあらわれた");
const dragon = new Monster("ドラゴン", 99999, 1000);
dragon.logState();

console.log("スライムの攻撃");
dragon.damage(slime.attack);
dragon.logState();

console.log("ドラゴンの攻撃");
slime.damage(dragon.attack);
slime.logState();
```

![スクリーンショット 2020-08-29 23.28.21.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/113504/eedcc6b7-f892-07a0-20b0-f52999fc652e.png)

# 課題2
自分のオリジナルモンスターを作って戦わせてみよ。