ユーザ用ツール

サイト用ツール


ecmascript:class

文書の過去の版を表示しています。


<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.m()`というコードを実行すると次のようにメソッドが検索される

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>

ecmascript/class.1757551808.txt.gz · 最終更新: by nullpon