ユーザ用ツール

サイト用ツール


ecmascript:class

差分

このページの2つのバージョン間の差分を表示します。

この比較画面へのリンク

両方とも前のリビジョン前のリビジョン
次のリビジョン
前のリビジョン
ecmascript:class [2025/09/09 06:02] nullponecmascript:class [2025/09/09 16:30] (現在) nullpon
行 1: 行 1:
 <markdown> <markdown>
 # class # class
 +
 +## クラス構文
  
 ```javascript ```javascript
行 36: 行 38:
   }    } 
 } }
-``` 
- 
-クラスの実態は関数。(JSのクラスはオブジェクト生成構文のシンタックスシュガーに過ぎない) 
- 
-```javascript 
-console.log(typeof Test);  // => function 
 ``` ```
  
行 55: 行 51:
 } }
 ``` ```
 +
 +## 関数と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となる
 +
  
 </markdown> </markdown>
ecmascript/class.1757397754.txt.gz · 最終更新: by nullpon