同じコンストラクタでオブジェクトを作成する
重要性: 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
で持っているものです。