ecmascript:class
差分
このページの2つのバージョン間の差分を表示します。
次のリビジョン | 前のリビジョン | ||
ecmascript:class [2025/09/09 06:02] – 作成 nullpon | ecmascript:class [2025/09/09 16:30] (現在) – nullpon | ||
---|---|---|---|
行 1: | 行 1: | ||
< | < | ||
# class | # class | ||
+ | |||
+ | ## クラス構文 | ||
```javascript | ```javascript | ||
行 36: | 行 38: | ||
} | } | ||
} | } | ||
- | ``` | ||
- | |||
- | クラスの実態は関数。(JSのクラスはオブジェクト生成構文のシンタックスシュガーに過ぎない) | ||
- | |||
- | ```javascript | ||
- | console.log(typeof Test); | ||
``` | ``` | ||
行 47: | 行 43: | ||
## 継承 | ## 継承 | ||
+ | ```javascript | ||
class Test2 extends Test { | class Test2 extends Test { | ||
// 拡張メソッド | // 拡張メソッド | ||
行 53: | 行 50: | ||
} | } | ||
} | } | ||
+ | ``` | ||
+ | |||
+ | ## 関数と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(); | ||
+ | ``` | ||
+ | |||
+ | ※ ただし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, | ||
+ | |||
+ | const h2 = new h.constructor(2); | ||
+ | ``` | ||
+ | |||
+ | ## prototypeプロパティ | ||
+ | |||
+ | コンストラクタ関数はprototypeというプロパティを持っている | ||
+ | |||
+ | ```javascript | ||
+ | console.log(Hoge.prototype); | ||
+ | ``` | ||
+ | |||
+ | classで定義したメソッドは、このprototypeプロパティが持っている。 | ||
+ | |||
+ | ```javascript | ||
+ | console.log(Hoge.prototype, | ||
+ | |||
+ | console.log(Hoge.prototype, | ||
+ | ``` | ||
+ | |||
+ | コンストラクタ関数を通して生成されたオブジェクトは`__proto__`というプロパティを持っており、コンストラクタ関数のprototypeにアクセスできる | ||
+ | |||
+ | ```javascript | ||
+ | console.log(h.__proto__.getName); | ||
+ | ``` | ||
+ | |||
+ | `h.__proto__`も`__proto__`を持っている。このようなprototypeの連鎖を**prototype chain**と呼ぶ | ||
+ | |||
+ | ```javascript | ||
+ | console.log(h.__proto__); | ||
+ | console.log(h.__proto__.__proto__); | ||
+ | ``` | ||
+ | |||
+ | 何も継承していないクラスの場合prototype chainは2つで終わりだが、継承すると継承した回数だけprototype chainは長くなる。 | ||
+ | |||
+ | prototype chainはメソッドの呼び出しに関係している。例えば`x.m()`というコードを実行すると次のようにメソッドが検索される | ||
+ | |||
+ | 1. `x`自身プロパティ一覧からmという名前のプロパティを探し、見つかったらメソッドとして実行する。なければ2へ | ||
+ | 2. `x, | ||
+ | 3. `x.__proto__.__proto__`のプロパティ一覧からmという名前の・・・、なければ4へ | ||
+ | 4. prototype chainの末端まで到達しても見つからない場合はTypeErrorとなる | ||
</ | </ |
ecmascript/class.1757397725.txt.gz · 最終更新: by nullpon