JavaScriptのnew時に何が起こっているか
目次
Javascriptにはクラスがないが、インスタンスはnewで作成できる。このインスタンス生成時に裏側で何が起きているかの挙動の説明になる。以下は、徹底マスターJavaScriptの教科書に書かれている内容とほぼ同じだが、多少の解説を加え自分用のメモとして置いておく。
例として、以下のコンストラクタを取り上げる。
// Personコンストラクタ
function Person(name) {
this.name = name;
}
// Person関数のprototypeにgreetingを追加
Person.prototype.greeting = function() {
return "こんにちは" + this.name;
}
このコンストラクタからインスタンスを作成する。
var p = new Person('maeda');
p.greeting();
どう動くかの流れ
まず、内部で空のオブジェクトが作成される。
var obj = {};
オブジェクトのプロトタイプ(継承元のオブジェクト)に、Personコンストラクタのプロトタイプオブジェクト(Person.prototype)を指定する。__proto__
がオブジェクトのプロトタイプを参照するプロパティ。
Personコンストラクタのプロトタイプを指定しているため、作成されたインスタンスはコンストラクタのprototypeに定義されたメソッドを利用できる。例のインスタンスがgreetingを利用できるのは、ここの設定があるため。
obj.__proto__ = Person.prototype;
コンストラクタを実行し、初期化する。このときにコンストラクタ自体のプロパティがコピーされる。arguments
はインスタンス作成時の引数(argumentsプロパティ)。
Person.apply(obj, arguments);
完成したオブジェクトを返す。
return obj
これがインスタンスそのもの。
余談
インスタンスは生成後、コンストラクタ自体との関係性はなくなっているが、コンストラクタ.prototype
(Person.prototype)をインスタンス.__proto__
(p.__proto__)で参照できる。Person.prototype
は、constructorプロパティ
を持ち、結びついているコンストラクタ名を取得できる。逆にコンストラクタから参照するときは、コンストラクタ.prototype
(Person.prorotype)になる。
尚、Person.prototype.__proto__
はObject.prototype
。Object.prototype.__proto__
はnull
となっている。自身のオブジェクトにないメソッドは上位の継承しているオブジェクトのものを使うという流れがこの仕組みでできている。いわゆるプロトタイプチェーン。