iT邦幫忙

3

不單純的 JavaScript 原型繼承

  • 分享至 

  • xImage

大家好!

先前研究 JavaScript 原型繼承的時候,就覺得非常不單純,例如:

function One() {}
function Two() {}

Two.prototype = Object.create(One.prototype);
Two.prototype.constructor = Two;
new Two(); // Two {}
Two.prototype; // One { ... }
Two.prototype instanceof One; // true

Two 繼承 One 後,就能發現 Two.prototype 是由 One 建構出的物件,因此 Two.prototype 很明顯就是 One 的實例。

然而,原生物件型別卻不是如此,例如:

[]; // Array []
Array.prototype; // Array [ ... ]
Array.prototype instanceof Array; // false

這裡 Array.prototype 是由同名Array 建構出的物件(父原型應為 Object 不是嗎?),不過 Array.prototype 卻不是 Array 的實例。

再來看一個:

new String(); // String {}
String.prototype; // String { ... }
String.prototype instanceof String; // false

這裡 String.prototype 也是由同名String 建構出的物件,但是 String.prototype 卻也不是 String 的實例。

綜上所述,我認為可能的原因是:

原生物件型別的物件原型所使用的建構式只有名稱相同而已,實際上是位於不同記憶體位置的建構式。

例如:

function One() {}
function Two() {}

Two.prototype = Object.create(Two.prototype);
Two.prototype.constructor = Two;
new Two(); // Two {}
Two.prototype; // Two { ... }
Two.prototype instanceof Two; // false

但是,如果要繼承就更麻煩了。
不知道各位有沒有其他的想法呢?

圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

1 個回答

1
居然解出來了
iT邦好手 1 級 ‧ 2022-03-12 08:10:56
最佳解答

原生物件型別的物件和原型所使用的建構式只有名稱相同而已,實際上是位於不同記憶體位置的建構式。

以過去學習的經驗,這算是設計上的小巧思
有時像設計第三方套件時
為了要避免"汙染全局"的屬性或方法
會用這種方式去隔開
以避免直接覆蓋掉原屬性方法

Felix iT邦研究生 2 級 ‧ 2022-03-12 15:28:41 檢舉

感謝回答。

確實如此,可惜無法重現 Array.prototype 為何是 Array 的實例。

ECMA-262 Edition 5.1
§15.4.4 Properties of the Array Prototype Object
§15.5.4 Properties of the String Prototype Object

規範也沒有解釋清楚,只有說 Array.prototype 本身就是 Array 而已,至於作法如何就不得而知了。

也有可能因為是直接指派原型的情況,導致原型鏈被破壞,也因此 Array.prototype 無法成為 Array 的實例?

我要發表回答

立即登入回答