JSのクラスなど初心者覚書

[クラス](https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Classes)を参考に初心者がメモ書きしています。

### クラス宣言

```js
class Rectangle{
  constructor(height,width){
    this.height = height;
    this.width = width;
  }
}
```

クラスにアクセスする前に、そのクラスを宣言する必要がある。
関数宣言だと、Hoistingがある。

```js
const p = new Rectangle(); // ReferenceError
```


### クラス式
名前付きでも名前なしでもできます。名前付きクラスの名前は、クラス内のローカルとして扱われます。(ただし (インスタンスのではなく) クラスの name プロパティによって取得可能)

```js
// 名前なし
let Rectangle = class {
  constructor(height, width) {
    this.height = height;
    this.width = width;
  }
};
console.log(Rectangle.name);
// 出力: "Rectangle"

// 名前つき
let Rectangle = class Rectangle2 {
  constructor(height, width) {
    this.height = height;
    this.width = width;
  }
};
console.log(Rectangle.name);
// 出力: "Rectangle2"
```

- クラス本体は Strict モード で実行される
  - Strictじゃない場合サイレントエラー

- "constructor" という名前のメソッドは、クラスに 1つしか定義できません。
  - 2回以上定義されている場合は、SyntaxError がスローされます。


[参考 メソッド定義](https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Functions/Method_definitions)
- 簡略構文は、ECMAScript 第 5 版で導入された getter や setter 構文に似ている

```js
car obj = {
  foo: fucnction(){
  /* コード */
  },
  bar: fucnction(){
  /* コード */
  }
};
```
以下のように短縮できる

```js
car obj = {
  foo(){
  /* コード */
  },
  bar(){
  /* コード */
  }
};
```

- すべてのメソッド定義がコンストラクターではない(簡略構文のみ！)ため、インスタンス化しようとすると TypeError が発生します。


### プロトタイプメソッド

```js

class Rectangle {
  constructor(height, width) {
    this.height = height;
    this.width = width;
  }
  // ゲッター
  get area() {
    return this.calcArea();
  }
  // メソッド
  calcArea() {
    return this.height * this.width;
  }
}
const square = new Rectangle(10, 10);
console.log(square.area); // 100

```
#### ゲッターってなんだろう？よくわからなかった、、

[ゲッター](https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Functions/get)

#### 動的に計算した値を返すプロパティにアクセスを許可したほうが望ましい場合とは？ （まだわからない）

- 明示的なメソッドを呼び出すことなく内部変数に状態を反映させたい場合があります。 JavaScript では、ゲッターを使ってこれを行うことが可能

- ゲッターを削除したい場合は、 delete を使用

### [ゲッターとセッターの定義](https://developer.mozilla.org/ja/docs/Web/JavaScript/Guide/Creating_New_Objects/Defining_Getters_and_Setters)

- ゲッターはある属性の値を取得するメソッドです。セッターは属性に値を設定するメソッドです。全ての定義済みコアオブジェクトと、新しいプロパティの追加をサポートしているユーザ定義オブジェクトに対してゲッターとセッターを定義できます。ゲッターとセッターの定義にはオブジェクトリテラル構文を使用します。

#### わからないこと：
- 新しいプロパティの追加をサポートしているというのがどういう状態なのか？
- オブジェクトリテラル構文？

- ゲッターもセッターも、

```js
__defineGetter__
```
および

```js
__defineSetter__
```
という 2 つの特別なメソッドを用いて、オブジェクト作成後でも、そのオブジェクトに追加することができます。両メソッドの第 1 引数にはそのゲッターやセッターの名前を文字列で指定します。第 2 引数にはゲッターやセッターとして呼び出す関数を指定します。前の例を別の方法で実装したものを以下に示します。

```js

o.__defineGetter__("b", function() { return this.a+1; });
o.__defineSetter__("c", function(x) { this.a = x/2; });
```

わわ、、わからないけど下記の記事を見たらわかったような。
（今の理解：　クラスの中のgetと書いてある一部分だけを取得できる。
setはgetとペアで使う？ためにセットするもの?）という意味だと解釈したが違っていたらコメントいただけるとありがたいです。

(class構文の使い方)[https://www.sejuku.net/blog/49551]
- ゲッターメソッドを作ることで、クラスの特定のプロパティを取得することができます。
例えば、「name」というプロパティをゲッターメソッドで定義すると次のようになります。

```js
class User {

    constructor( name, age ) {
        this.name = name;
        this.age = age;
    }

    //ゲッターメソッド
    get myName() {
        return this.name;
    }
}
```
使い方

```js
var taro = new User('太郎', 32);
console.log( taro.myName );
```

##### セッター

```js
class User {
    constructor( name, age ) {
        this.name = name;
        this.age = age;
    }
    //セッターメソッド
    set myName( value ) {
        this.name = value;
    }
    // ゲッターメソッド
    get myName() {
        return this.name;
    }
}
```
使い方

```js
var taro = new User('太郎', 32);
taro.myName = '花子';
console.log( taro.myName );
```




### 静的メソッド
静的メソッドは、クラスのインスタンス化なしで呼ばれ、インスタンス化されていると呼べない

```js

class Point {
  constructor(x, y) {
    this.x = x;
    this.y = y;
  }

  static distance(a, b) {
    const dx = a.x - b.x;
    const dy = a.y - b.y;

    return Math.hypot(dx, dy);
  }
}

const p1 = new Point(5, 5);
const p2 = new Point(10, 10);
p1.distance; //未定義
p2.distance; //未定義

console.log(Point.distance(p1, p2)); // 7.0710678118654755
```

- this に値が付けられずに静的メソッドまたはプロトタイプメソッドが呼ばれると、this の値はメソッド内で undefined になる