同じコンストラクタでオブジェクトを作成する
コンストラクタ関数によって作成された任意のオブジェクト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
を使用することはありません。