js实例化以及constructor探究
先来一个构造函数:
function Person(name){
this.name=name;
}
对其添加原型链:
Person.prototype={
getName:function(){
return this.name;
}
}
对其实例化:
var person=new Person('xiaopu');
这样完成一个基本的构造函数加原型链的组合封装。
我们不去探究原型链的过程 这个可以参考前边的文章
我们来主要研究一下实例化过程,以及实例化前后constructor的指向问题:
实例化过程:
实例化其实是一个new的过程,在这里将其分为四步去执行
1.实例一个object对象
2.将构造函数的作用域置入该object
3.将构造函数赋值到object
4.执行object代码
在这个过程中 首先是实例化一个object,所以新的实例person实际是通过Object继承而来的。
也就是说person instanceof Object==person instanceof Person==true
constructor指向:
每个构造函数都有一个prototype属性,这个属性指针指向的是一个object,
每个对象都有一个constructor指针,这个指针指向的是创建该对象实例的构造函数。
当然函数也是对象也会有constructor属性例如Person.constructor就指向了Function,因为Function是它的构造函数,也就是说Person是Function的实例。
1.
上面代码我们重写如下:
function Person(name){
this.name=name;
}
var person=new Person('xiapu');
此时Person.prototype是一个空对象,
而person.constructor指向的是Person,Person.prototype.constructor指向的也是Person
2.
当我们显示的对构造函数进行原型扩展后
Person.prototype={
getName:function(){return this.name}
}
这个时候person.constructor以及Person.prototype.constructor都指向的是Object而不是Person
究其原因,是因为一个新对象赋值给了Person.prototype,此时的Person.prototype是一个object的实例。
这个object的constructor指向的肯定就是object的构造函数类Object,所以二者的constructor都会指向Object
如果constructor对于你的判断很重要 可以在原型中添加constructor并将其赋值为Person
Person.prototype={
constructor:Person,
getName:function(){return this.name}
}
3.
而如果以Person.prototype.getName=function(){return this.name}去定义原型对象,
此时的constructor就不存在新建一个object过程,那么二者的指向依然会是Person
但是如果一开始用对象方式声明prototype然后又用原型链去声明原型属性 那么此时二者的constructor依然指向的是Object,因为对象方式声明的prototype已经覆盖了原先构造函数中存在的原型链。
即:Person.prototype={};
Person.prototype.getName=function(){return this.name}