constructor 未指向建構函式

admin發表於2018-11-24

constructor 翻譯成漢語是構造器的意思。

恰如其名,物件例項的constructor 屬性通常是指向建構函式。

關於此屬性更多內容參閱JavaScript constructor一章節。

程式碼例項如下:

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

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

a:3:{s:3:\"pic\";s:43:\"portal/201811/24/002434hf4jn5mvi4infnko.png\";s:5:\"thumb\";s:0:\"\";s:6:\"remote\";N;}

f是建構函式Foo的物件例項,很自然f.constructor指向Foo。

通常認為這是自然且永恆的事情,然而事實有時候會讓人比較意外。

由此可能會導致一些莫名其妙的錯誤,且不容易查詢,因為您已經堅信那地方是正確無比的。

下面演示一下讓人意外的現象,看如下程式碼例項:

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

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

a:3:{s:3:\"pic\";s:43:\"portal/201811/24/002500cz1tk0uxymd1lyx1.png\";s:5:\"thumb\";s:0:\"\";s:6:\"remote\";N;}

列印結果是false,也就是說constructor並未指向建構函式。

難不成f並非建構函式Foo的物件例項,其實不然,f肯定是Foo的物件例項,constructor沒有指向F也並不不妥。

下面對形成上述現象的原因分步進行一下詳細分析:

(1).首先,物件例項本身並沒有constructor屬性,它是繼承自原型鏈。

(2).預設情況下,建構函式原型物件的constructor屬性被人為設計為指向建構函式。

(3).所以,如果沒有其他改動,物件例項會繼承constructor屬性,很自然,它會指向建構函式。

下面開始進入關鍵點,分析為什麼沒有指向建構函式:

Foo.prototype={},這是什麼操作,這是重置原型物件,再強調一下是重置而不僅僅是修改。

整個原型物件被替換掉,新原型物件constructor屬性自然會指向構建它的建構函式。

特別說明:如無必要的原因,儘量不要重置原型物件。

程式碼演示如下:

[JavaScript] 純文字檢視 複製程式碼執行程式碼
function Foo(){}
Foo.prototype={}
let f=new Foo();
console.log(Foo.prototype.constructor===Object);
console.log(f.constructor===Object);

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

a:3:{s:3:\"pic\";s:43:\"portal/201811/24/002651rvlkslff7reamgas.png\";s:5:\"thumb\";s:0:\"\";s:6:\"remote\";N;}

執行結果說明了一切,新原型物件中的constructor不會自動指向F,而是指向建立它的建構函式。

所以我們要人為的對它的指向進行一下調整,程式碼修改如下:

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

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

a:3:{s:3:\"pic\";s:43:\"portal/201811/24/002551oloxpu2u8pqztoub.png\";s:5:\"thumb\";s:0:\"\";s:6:\"remote\";N;}

很簡單的操作,重置一下constructor指向即可,於是一切歸於正常。

此操作通常是必須的,否則將難以追尋物件例項是由哪個建構函式建立。

相關文章