類別延伸物件?
重要性:3
我們知道,所有物件通常會繼承自 Object.prototype
,並存取「一般」物件方法,例如 hasOwnProperty
等。
例如
class Rabbit {
constructor(name) {
this.name = name;
}
}
let rabbit = new Rabbit("Rab");
// hasOwnProperty method is from Object.prototype
alert( rabbit.hasOwnProperty('name') ); // true
但如果我們明確寫成 "class Rabbit extends Object"
,那結果會和單純的 "class Rabbit"
不一樣嗎?
差異在哪裡?
以下是此類程式碼的範例(它無法執行,為什麼?請修正它)
class Rabbit extends Object {
constructor(name) {
this.name = name;
}
}
let rabbit = new Rabbit("Rab");
alert( rabbit.hasOwnProperty('name') ); // Error
首先,讓我們看看為什麼後面的程式碼無法執行。
如果我們嘗試執行,原因就會變得明顯。繼承類別建構函式必須呼叫 super()
。否則 "this"
將不會被「定義」。
因此,以下是修正方法
class Rabbit extends Object {
constructor(name) {
super(); // need to call the parent constructor when inheriting
this.name = name;
}
}
let rabbit = new Rabbit("Rab");
alert( rabbit.hasOwnProperty('name') ); // true
但這還不是全部。
即使在修正之後,"class Rabbit extends Object"
和 class Rabbit
之間仍然存在一個重要的差異。
正如我們所知,「extends」語法設定了兩個原型
- 建構函式(用於方法)的
"prototype"
之間。 - 建構函式本身(用於靜態方法)之間。
在 class Rabbit extends Object
的情況下,表示
class Rabbit extends Object {}
alert( Rabbit.prototype.__proto__ === Object.prototype ); // (1) true
alert( Rabbit.__proto__ === Object ); // (2) true
因此,Rabbit
現在透過 Rabbit
提供對 Object
的靜態方法的存取,如下所示
class Rabbit extends Object {}
// normally we call Object.getOwnPropertyNames
alert ( Rabbit.getOwnPropertyNames({a: 1, b: 2})); // a,b
但是,如果我們沒有 extends Object
,則 Rabbit.__proto__
沒有設定為 Object
。
以下是示範
class Rabbit {}
alert( Rabbit.prototype.__proto__ === Object.prototype ); // (1) true
alert( Rabbit.__proto__ === Object ); // (2) false (!)
alert( Rabbit.__proto__ === Function.prototype ); // as any function by default
// error, no such function in Rabbit
alert ( Rabbit.getOwnPropertyNames({a: 1, b: 2})); // Error
因此,在這種情況下,Rabbit
沒有提供對 Object
的靜態方法的存取。
順帶一提,Function.prototype
也有「一般」函式方法,例如 call
、bind
等。它們最終在兩種情況下都可用,因為對於內建的 Object
建構函式,Object.__proto__ === Function.prototype
。
以下是圖片
因此,簡而言之,有兩個差異
class Rabbit | class Rabbit extends Object |
---|---|
– | 需要在建構函式中呼叫 super() |
Rabbit.__proto__ === Function.prototype |
Rabbit.__proto__ === Object |