同じコンストラクタでオブジェクトを作成する
重要性: 5
想像してください、コンストラクタ関数によって作成された任意のオブジェクト obj があります – 今、それを使って新しいオブジェクトを作りたいです。
私たちは、このようにすることができるでしょうか?
let obj2 = new obj.constructor();
このコードを正しく動作させる obj のコンストラクタ関数の例を提示してください。そして、間違って動作する例も提示してください。
もし "constructor" プロパティが正しい値を持っていることが確かであるなら、私たちはこのようなアプローチを使うことができます。
例えば、デフォルトの "prototype" を触らないのであれば、このコードは確実に動作します:
function User(name) {
this.name = name;
}
let user = new User('John');
let user2 = new user.constructor('Pete');
alert( user2.name ); // Pete (worked!)
User.prototype.constructor == User であるため、これは動作します。
…しかし、いわば誰かが User.prototype を上書きし、"constructor" を再作成するのを忘れている場合、それは失敗するでしょう。
例:
function User(name) {
this.name = name;
}
User.prototype = {}; // (*)
let user = new User('John');
let user2 = new user.constructor('Pete');
alert( user2.name ); // undefined
なぜ user2.name が undefined なのでしょう?
ここで、new user.constructor('Pete') は次のように動作します:
- 最初に、
userの中でconstructorを探します。ありません。 - 次に、プロトタイプチェーンに沿います。
userのプロトタイプはUser.prototypeで、これもconstructorを持っていません。 User.prototypeの値は普通のオブジェクト{}であり、そのプロトタイプはObject.prototypeです。そして、Object.prototype.constructor == Objectがあります。なので、これが使われます。
最終的に、let user2 = new Object('Pete') となります。組み込みの Object コンストラクタは引数を無視し、常に空のオブジェクトを生成します – これは、結局私たちが user2 で持っているものです。