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}