オブジェクトの初期化で使用されたコンストラクタ関数を参照するconstructorプロパティ。
constructorプロパティはコンストラクタのprototypeのプロパティであり、インスタンスからはprototypeを通じてアクセスすることができる。
コンストラクタのprototypeにプロパティ/メソッドを追加する方法によってconstructorプロパティに入る値が変わるので注意。
1,コンストラクタのconstructorプロパティが削除される
function ClassA(){};
ClassA.prototype = {
say : function(){}
};
var a = new ClassA();
console.log(a.constructor); // Object
ClassA.prototypeに新しいオブジェクトを代入するとClassAのprototypeがconstructorプロパティごと上書きされ、constructorプロパティにはプロトタイプチェーンを遡りObjectが入る。
2,コンストラクタのconstructorプロパティが保持される
function ClassB(){};
ClassB.prototype.say = function(){};
var b = new ClassB();
console.log(b.constructor); //ClassB
新しいオブジェクトを代入せず、ClassB.prototypeに直接プロパティ/メソッドを定義する方法であればClassBのconstructorプロパティが保持される
3,constructorプロパティを直接定義する
function ClassC(){};
ClassC.prototype = {
say : function(){},
constructor : ClassC
};
var c = new ClassC();
console.log(c.constructor); //ClassC
for(var p in c){
console.log(p); //consructorが列挙される
}
ClassC.prototypeに新しいオブジェクトを代入し、その中でconstructorプロパティを定義し値をClassCとすればconstructorプロパティを設定できるが、constructorプロパティがfor-inで列挙されてしまう。
4,constructorプロパティを直接定義する方法で、for-in時に列挙されないようにする
function ClassD(){};
ClassD.prototype = {
say : function(){}
};
Object.defineProperty(ClassD.prototype, 'constructor', {
value : ClassD,
enumerable : false
});
var d = new ClassD();
console.log(d.constructor); //ClassD
for(var p in d){
console.log(p); //consructorが列挙されない
}
ECMA-262 5th editionで導入されているObject.definePropertyを使用してfor-in時に列挙されないようenumerableの値をfalseにする
雑感
普段あまり意識しないconstructorプロパティ。
使いどころもそんなに無いと思うけどクラス生成メソッド等を作る時は意識するようにしないと。
個人的にはシンプルに「2」で良いかなと思うけど、prototypeっていちいち書くのがめんどくさければ即時関数に入れちゃう方法もある。
function ClassE(){}
(function(p){
p.say = function(){};
})(ClassE.prototype);
var e = new ClassE();
console.log(e.constructor); //ClassE