メソッドとは
プログラム中は、意味や内容がまとまっている処理や、繰り返し現れる処理を、ひとつのグループとしてまとめます。
コンストラクタとは
あらかじめ定義されたクラスをインスタンスに転化する仕組みです。
JavaScriptのメソッドとコンストラクタ
function foo() {
return 1
}
var v = foo(); // fooをメソッドとして扱う
var o = new foo(); // fooをコンストラクタとして扱う
JavaScript の 「function」キーワード はメソッド、コンストラクタ両方を宣言することが可能です。
メソッドオブジェクトとコンストラクタオブジェクト
メソッドオブジェクトとは:a object with [[call]] private field
コンストラクタオブジェクトとは:a object with [[construct]] private field
つまり、[[call]] private fieldをもつオブジェクは、メソッドとして呼び出すことができます。
[[construct]] private fieldをもつオブジェクは、コンストラクタとして呼び出すことができます。
「function」キーワードで生成されたメソッド(実はオブジェクト)は必ず[[call]] private field、[[construct]] private field両方を持ち、メソッドまたはコンストラクタとして扱われます。
まだ例に戻りましょう
var o = new foo(); // 何が発生したのか
[[construct]]を呼びされた場合、発生したことは以下になります:
- Object.protoypeをprotoypeとして新しいオブジェクトを生成する
- step1で生成したオブジェクトの[[call]]を実行する
- [[call]]の戻り値がオブジェクト->この値を返す
- [[call]]の戻り値がオブジェクト以外->step1で生成したオブジェクトを返す
ちなみに、[[construct]]を呼ぶことで新しいオブジェクトを返された場合は(step3)、このオブジェクトがクロージャになります。(外部からこのオブジェクトのプロパティをアクセスできないため)、例えば:
function foo(){
this.a = 100;
return {
getA: function() {
return this.a;
}
}
}
var f = new foo;
f.getA(); //100
//f.a 外からアクセスできない
クラスの定義と関数の定義の切り分け
クラスの定義と関数の定義とも「function」キーワードを使っているのは何となく気持ち悪いのでなんかいい方法があります?
「class」キーワード
es6から「class」キーワードがサポートしているため、new class()でコンストラクタ処理を行えるようになります。
アロー関数
アロー関数とは、より短く記述できる、通常の function 式の代替構文です(javaのlambda関数みたいなやつ)
アロー関数で生成したのは関数だけ、コンストラクタとして扱わないです。
new (v => 0) // error
まとめ
「function」キーワードで生成されたメソッドはメソッドまたはコンストラクタとして扱われます。
「function」キーワードを使わず、関数宣言の場合はアロー関数、クラス宣言の場合は「class」キーワードの方が個人的良いのではないかと思います。