使用相同的建構函式建立物件
重要性:5
想像一下,我們有一個任意物件 obj
,是由建構函式建立的,我們不知道是哪一個,但我們想使用它來建立一個新的物件。
我們可以這樣做嗎?
let obj2 = new obj.constructor();
提供一個 obj
建構函式的範例,讓這樣的程式碼可以正確執行。以及一個讓它執行錯誤的範例。
如果我們確定 "constructor"
屬性有正確的值,我們可以使用這種方法。
例如,如果我們不變更預設的 "prototype"
,那麼這個程式碼一定會執行
function User(name) {
this.name = name;
}
let user = new User('John');
let user2 = new user.constructor('Pete');
alert( user2.name ); // Pete (worked!)
它執行成功,因為 User.prototype.constructor == User
。
…但如果有人(姑且這麼說)覆寫了 User.prototype
,卻忘記重新建立 constructor
來參照 User
,那麼就會失敗。
例如
function User(name) {
this.name = name;
}
User.prototype = {}; // (*)
let user = new User('John');
let user2 = new user.constructor('Pete');
alert( user2.name ); // undefined
為什麼 user2.name
是 undefined
?
以下是 new user.constructor('Pete')
的運作方式
- 首先,它在
user
中尋找constructor
。沒有。 - 接著,它遵循原型鏈。
user
的原型是User.prototype
,它也沒有constructor
(因為我們「忘記」正確設定它!)。 - 在鏈中往上,
User.prototype
是個純粹物件,它的原型是內建的Object.prototype
。 - 最後,對於內建的
Object.prototype
,有一個內建的Object.prototype.constructor == Object
。因此它會被使用。
最後,在最後,我們有 let user2 = new Object('Pete')
。
這可能不是我們想要的。我們想要建立 new User
,而不是 new Object
。那是遺失 constructor
的結果。
(如果你好奇的話,new Object(...)
呼叫會將其引數轉換為物件。那是一個理論上的東西,實際上沒有人會使用值呼叫 new Object
,而且我們通常不會使用 new Object
來建立物件)。