同じコンストラクタでオブジェクトを作成する
コンストラクタ関数によって作成された任意のオブジェクト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を上書きし、Userを参照するように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の場合、組み込みのObject.prototype.constructor == Objectがあります。そのため、これを使用します。
最後に、let user2 = new Object('Pete')になります。
おそらく、それが私たちが求めていることではありません。new Userを作成したいのであって、new Objectではありません。これは、constructorがないことの結果です。
(念のためですが、new Object(...)の呼び出しはその引数をオブジェクトに変換します。これは理論的なことで、実際には new Objectを値で呼び出す人はおらず、一般にオブジェクトを作成するために new Objectを使用することはありません。