文書の過去の版を表示しています。
<markdown> # class
## クラス構文
```javascript class Test {
// 静的フィールド
static version = '1.0.0';
// 静的メソッド
static info() {
  // 注意 staticコンテキストでのthis.nameはクラス名を指す(`#name`ではない)
  return `${this,name} class, version ${this.version}`
}
// privateフィールド
#name = '';
// コンストラクタ
constructor(v) {
  this.#name = v;
}
// メソッド
getMessage() {
  return 'Hello from ${this.#name}'
}
// getter
get name() {
  return this.#name;
}
// setter
set name(v) {
  this.#name = v;
} 
} ```
## 継承
```javascript class Test2 extends Test {
// 拡張メソッド
print() {
  console.log(this.getMessage());
}
} ```
## 関数とnew
ここからはマニア向けのディープな話になる。JSの関数はコンストラクタとして機能し、new演算子によって新しいオブジェクトを生成できる
```javascript function Fuga(x) {
this.x = x;
}
const fuga = new Fuga(1);
console.log(typeof Fuga); ⇒ function 普通の関数としても呼べる Fuga(); ```
以下のコードは実は上記のコードとほぼ同等。class構文で定義したクラスは実は関数なのである。このような関数はコンストラクタ関数と呼ばれる
```javascript class Fuga {
constructor(x) {
  this.x = x;	
}
} const fuga = new Fuga(1);
console.log(typeof Fuga); ⇒ function ただしclassで定義した関数は直接呼べないように制限がかかっている Fuga(); TypeError: Class constructor Fuga cannot be invoked without 'new' ``` ※ ただしfunctionによるコンストラクタ定義は過去のコードとの互換性のために残されているので現在は非推奨でありclassキーワードを使うべき これは何を意味しているかというとclassと銘打っているが、その実体はクラスではないということだ。クラスのような振る舞いはprototype chainという仕組みで行われている。 ## constructorプロパティ 生成されたオブジェクトはconstructorというプロパティを持っている。これは自身を生成したコンストラクタ関数への参照である。 ```javascript class Hoge { constructor(name) { this.name = name; } getName() { return this.name; } } const h = new Hoge(1) console.log(h,constructor === Hoge); ⇒ true
const h2 = new h.constructor(2); newすることもできる ``` ## prototypeプロパティ コンストラクタ関数はprototypeというプロパティを持っている ```javascript console.log(Hoge.prototype); ``` classで定義したメソッドは、このprototypeプロパティが持っている。 ```javascript console.log(Hoge.prototype,getName); ⇒ [function getName]
console.log(Hoge.prototype,getName.call({ name: “にゃん” })); ⇒ にゃん ``` コンストラクタ関数を通して生成されたオブジェクトは`proto`というプロパティを持っており、コンストラクタ関数のprototypeにアクセスできる ```javascript console.log(h.proto.getName); ⇒ [function getName] ```
`h.proto`も`proto`を持っている。このようなprototypeの連鎖をprototype chainと呼ぶ
```javascript console.log(h.proto); ⇒ {} console.log(h.proto.proto); ⇒ [Object: null prototype] {} ```
何も継承していないクラスの場合prototype chainは2つで終わりだが、継承すると継承した回数だけprototype chainは長くなる。
prototype chainはメソッドの呼び出しに関係している。例えば`x.)`というコードを実行すると次のようにメソッドが検索される
1. `x`自身プロパティ一覧からmという名前のプロパティを探し、見つかったらメソッドとして実行する。なければ2へ 2. `x,proto`のプロパティ一覧からmという名前の・・・、なければ3へ 3. `x.proto.proto`のプロパティ一覧からmという名前の・・・、なければ4へ 4. prototype chainの末端まで到達しても見つからない場合はTypeErrorとなる
### prototypeを指定してオブジェクトを生成
`Object.create`を使うと任意のオブジェクトをprototypeに設定して新しいオブジェクトを生成できる
```javascript const p = {
name: 'proto',
greet() {
  console.log("I am a " + this.name)
}
}
pをプロトタイプに設定してオブジェクトを生成 const h = Object.create(p); console.log(h.proto === p); ⇒ true
prototypeのnameが使われる h.greet(); ⇒ I am a proto
hのnameを設定 h,name = “cat”; h自身がnameを持っていれば、プロトタイプではなく自身のnameが使われる h.greet(); ⇒ I am a cat ``` - [Object.create() - JavaScript | MDN(developer.mozilla.org)](https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/Object/create) </markdow n>