今天发现自己又搞不明白prototype、proto、constructor这些属性直接的区别了。。故此总结一下O_0·
function Person() {
this.category = 'human'
}
function Female() {
this.sex = 'female'
}
Female.prototype = new Person()
var xia = new Female()
var chinese = new Person()
以上例子中,有两个类,Person类,和Female类,Female类的prototype属性为Person类的一个实例,而xia和chinese则分别是Female类和Person类的实例
prototype
表示对象的原型。
xia.prototype // undefined
Female.prototype // Person {category: 'human'}
Person.prototype // Object {contructor: person(), __proto__: Object}
_proto_
xia.__proto__ // Person {category: 'human'}
Female.__proto__ // function () {}
Person.__proto__ // function () {}
出现这种情况的主要原因是以下两点:
1. 所有构造器/函数的都指向Function.prototype,它是一个空函数(Empty function)
2. 所有对象的proto都指向其构造器的prototype,即chinese.constructor.prototype === chinese.__proto__
由上可知,xia.__proto__ === xia.constructor.prototype
,而xia.constructor这里为啥等于Person函数嘞?看下面的constructor的讲解
constructor
xia.constructor // function Person() {this.category = 'human'}
constructor始终指向创建当前对象的构造(初始化)函数。
任何一个prototype对象都有一个constructor属性,指向它的构造函数。
每一个实例也有一个constructor属性,默认调用prototype对象的constructor属性。即xia.constructor === Female.prototype.constructor
每个函数都有一个默认的属性prototype,而这个prototype的constructor默认指向这个函数
正常情况下,xia.constructor即是Female.prototype,应该指向其构造函数,也就是Female(),但是由于之前将Female.prototype指向了Person类的实例,即Person {category: 'human'},故
xia.constructor === Female.prototype === chinese.constructor === function Person () {}
这样看来,是很不好的,导致继承链的紊乱(xia明明是用构造函数Female生成的),因此我们必须手动纠正,将Female.prototype对象的constructor值改为Female.prototype.constructor = Female
这是很重要的一点,编程时务必要遵守。下文都遵循这一点,即如果替换了prototype对象,那么,下一步必然是为新的prototype对象加上constructor属性,并将这个属性指回原来的构造函数。