JavaScript constructor

admin發表於2018-10-09

constructor翻譯成漢語是構造器意思,有圖為證:

a:3:{s:3:\"pic\";s:43:\"portal/201810/09/161059cvv39tqk4jmjn3jb.png\";s:5:\"thumb\";s:0:\"\";s:6:\"remote\";N;}

預設,物件例項的constructor屬性指向建立此例項的構造器。

更多情況下,我們稱構造器為建構函式。

程式碼例項如下:

[JavaScript] 純文字檢視 複製程式碼
function Antzone(){
  // code
}  
let ant=new Antzone();

上面程式碼,ant是物件例項,Antzone則是構造器,也就是建構函式。

那麼ant的constructor屬性指向構造器Antzone。

程式碼例項如下:

[JavaScript] 純文字檢視 複製程式碼執行程式碼
function Antzone(){
  // code
}  
let ant=new Antzone();
console.log(ant.constructor===Antzone);

程式碼執行效果截圖如下:

a:3:{s:3:\"pic\";s:43:\"portal/201810/09/161145we57a0f5tpp5p83t.png\";s:5:\"thumb\";s:0:\"\";s:6:\"remote\";N;}

再來看一段程式碼例項:

[JavaScript] 純文字檢視 複製程式碼執行程式碼
let str="螞蟻部落";
let arr=["螞蟻部落",4,"青島市南區"];
console.log(str.constructor===String);
console.log(arr.constructor===Array);

程式碼執行效果截圖如下:

a:3:{s:3:\"pic\";s:43:\"portal/201810/09/161219tgz78vgeuv766u68.png\";s:5:\"thumb\";s:0:\"\";s:6:\"remote\";N;}

使用直接量方式建立字串或者陣列等物件例項,本質上內部還是採用建構函式建立。

[JavaScript] 純文字檢視 複製程式碼執行程式碼
function Antzone(webName){
  this.webName=webName;
}
Antzone.prototype.url="http://www.softwhy.com";
let antzone=new Antzone("螞蟻部落");
console.log(antzone.constructor === Antzone);
console.log(Antzone.prototype.constructor===Antzone);

程式碼執行效果截圖如下:

a:3:{s:3:\"pic\";s:43:\"portal/201810/09/161246n25da9ynkyy92kpd.png\";s:5:\"thumb\";s:0:\"\";s:6:\"remote\";N;}

程式碼分析如下:

(1).antzone是建構函式Antzone的物件例項。

(2).那麼很自然antzone.constructor會指向它的建構函式Antzone。

(3).為什麼建構函式的原型物件的constructor屬性也會指向Antzone呢,這裡的原型物件並非由建構函式Antzone建立,是不是很奇怪,再來看一段程式碼例項:

[JavaScript] 純文字檢視 複製程式碼執行程式碼
function Antzone(webName){
  this.webName=webName;
}
Antzone.prototype={
  address:"青島市南區",
  age:4
};
let antzone=new Antzone("螞蟻部落");
console.log(antzone.constructor === Antzone);
console.log(Antzone.prototype.constructor===Antzone);

程式碼執行效果截圖如下:

a:3:{s:3:\"pic\";s:43:\"portal/201810/09/161320tr8kgr1qhqh6bcdz.png\";s:5:\"thumb\";s:0:\"\";s:6:\"remote\";N;}

上面程式碼的列印結果都是false,尤其是第一個結果更加令人難以理解。

因為antzone實實在在是Antzone的物件例項。

現象解釋如下:

(1).建構函式內部並沒有constructor屬性,驗證如下:

[JavaScript] 純文字檢視 複製程式碼執行程式碼
function Antzone(webName){
  this.webName=webName;
}
let antzone=new Antzone("螞蟻部落");
console.log(antzone.hasOwnProperty("constructor"));

程式碼執行效果截圖如下:

a:3:{s:3:\"pic\";s:43:\"portal/201810/09/161407zx9eeuglzmqxze9q.png\";s:5:\"thumb\";s:0:\"\";s:6:\"remote\";N;}

hasOwnProperty方法可以判斷指定屬性是否是物件的自有屬性,非原型鏈繼承而來。

建構函式也是Function建構函式的例項,所以建構函式也是一個物件例項,它自然也有constructor屬性,不過此時constructor是建構函式的靜態屬性。

關於靜態屬性和例項屬性可以參閱JavaScript靜態屬性和例項屬性一章節。

(2).實質上,預設建構函式prototype原型物件是有Object()建構函式建立。

雖然實質上如此,但是ES依然會人為的將prototype物件的constructor屬性指向建構函式。

否則將無法判斷一個物件例項具體由哪一個建構函式建立。

再回到前面令人疑惑的程式碼:

[JavaScript] 純文字檢視 複製程式碼執行程式碼
function Antzone(webName){
  this.webName=webName;
}
Antzone.prototype={
  address:"青島市南區",
  age:4
};
let antzone=new Antzone("螞蟻部落");
console.log(antzone.constructor === Antzone);
console.log(Antzone.prototype.constructor===Antzone);

程式碼執行效果截圖如下:

a:3:{s:3:\"pic\";s:43:\"portal/201810/09/161454o8iraanvica77nbv.png\";s:5:\"thumb\";s:0:\"\";s:6:\"remote\";N;}

程式碼分析如下:

上面程式碼是重置物件原型,而不是修改物件原型,也就是更換了一個新的原型物件,所以原型物件的constructor屬性就不再是人為的指向建構函式的情況,而是指向它真正的建構函式Object:

[JavaScript] 純文字檢視 複製程式碼執行程式碼
function Antzone(webName){
  this.webName=webName;
}
Antzone.prototype={
  address:"青島市南區",
  age:4
};
let antzone=new Antzone("螞蟻部落");
console.log(antzone.constructor === Object);

程式碼執行效果截圖如下:

a:3:{s:3:\"pic\";s:43:\"portal/201810/09/161529i7fc44ttpw3fi43x.png\";s:5:\"thumb\";s:0:\"\";s:6:\"remote\";N;}

所以上述程式碼需要進行一下修改,否則就無法判斷出物件例項是由誰建立的。

程式碼例項如下:

[JavaScript] 純文字檢視 複製程式碼執行程式碼
function Antzone(webName){
  this.webName=webName;
}
Antzone.prototype={
  address:"青島市南區",
  age:4
};
Antzone.prototype.constructor=Antzone;
let antzone=new Antzone("螞蟻部落");
console.log(antzone.constructor === Antzone);

程式碼執行效果截圖如下:

a:3:{s:3:\"pic\";s:43:\"portal/201810/09/161602crjnqj7q7jmv17j5.png\";s:5:\"thumb\";s:0:\"\";s:6:\"remote\";N;}

只要將原型物件的constructor屬性重新指向建構函式即可。

相關文章