JavaScript中constructor属性一直不是很清楚,今日终于弄清了其中缘由,下面举例说明。
首先是一个典型的JavaScript实例声明:
function Person(){
this.name = name;
}
var p = new Person('Joe');
console.log(p.constructor === Person); //true
console.log(p.__proto__ === Person.prototype); //true
如果此时对Person的prototype中添加属性或函数:
function Person(){
this.name = name;
}
Person.prototype.getName = function(){
return this.name;
}
var p = new Person('Joe');
console.log(p.constructor === Person); //true
console.log(p.__proto__ === Person.prototype); //true
但是如果对Person的prototype重新定义,将会产生如下结果:
function Person(){
this.name = name;
}
Person.prototype = {
getName : function(){
return this.name;
}
}
var p = new Person('Joe');
console.log(p.constructor === Person); //false
console.log(p.__proto__ === Person.prototype); //true
这里面关系到constructor属性的归属问题,本人试着用下面的代码验证:
Person.__proto__.constructor===Person.constructor //true
p.__proto__.constructor === p.constructor; //true
经过上述验证,可以证明constructor其实是__proto__的属性(此处存疑,因为是个人验证,不清楚上面的验证代码是否精准,如果有误,希望各位指出)。
根据new的工作原理(详见http://www.cnblogs.com/ihardcoder/p/3667372.html),我们知道
p.__proto__ = Person.prototype;
所以
p.constructor = p.__proto__.constructor = Person.prototype.constructor
这样就将问题追溯到Person的prototype指向问题。当用Person.prototype = {}的方式重新定义时,同样根据new的工作原理,其实产生如下改变:
Person.prototype.__proto__ = Object.prototype
从而
p.constructor
= Person.prototype.constructor
= Person.prototype.__proto__.constructor
= Object.prototype.constructor
此时
p.constructor === Object; //true
如何避免constructor属性的混乱,归根结底,我们需要做的是保证instance的constructor属性指向Person.prototype.constructor,而不是Person的父类,所以当修改Person.prototype时需要保证Person.prototype.constructor指向自己。
function Person(){
this.name = name;
}
Person.prototype = {
getName : function(){
return this.name;
}
}
Person.prototype.constructor = Person;
var p = new Person('Joe');
console.log(p.constructor === Person); //false
console.log(p.__proto__ === Person.prototype); //true