在js中经常可以接触到prototype、prototype.constructor、constructor.prototype,感觉像一个圈一样,绕来绕去,他们是什么关系,什么时候该用哪一个,这是让很多新学js的人困惑的问题。
我们知道在js中,prototype是函数的原型,定义了一类对象共有的属性(通常都是方法),是该类对象的"blueprint"。
constructor是对象的构造函数,当我们通过声明一个构造函数来创建“类”时,constructor属性被隐性的添加到该"类"的prototype上,指向该构造函数自己。我们可以通过下面的代码验证:
function ClassA(){} console.log(ClassA.prototype.constructor == ClassA); //true
之所以把构造函数自身的引用又添加到prototype,目的是方便我们区分不同对象的实例。
当我们执行var a = new ClassA()时,在堆内存中生成一个新的object,然后将隐性的创建__proto__属性指向ClassA的prototype,最后将该object的地址赋给栈中的变量a,这样我们就通过a可以访问到在ClassA的prototype上定义的一些属性方法。所以
function ClassA(){} var a = new ClassA(); console.log(a.constructor === ClassA); //true
既然a.constructor是ClassA,那么a.constructor.prototype当然就是ClassA的prototype了。
值得注意的是虽然通过
ClassA.prototype = {
set = function (){},
get = function (){}
}
的形式来添加原型方法很方便,却忽略了会重写ClassA原有的prototype,导致丢失constructor属性,所实例化的对象的constructor属性将变为function Object(){[native code]}。解决的办就是自己手动将constructor属性赋值给ClassA。
另外,由于任何function都是由Function对象实例化来的,所以每个function的constructor都指向Function(){}
function ClassA(){} console.log(ClassA.constructor); // function Function(){[native code]}