大家好!
先前研究 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
但是,如果要繼承就更麻煩了。
不知道各位有沒有其他的想法呢?
原生物件型別的物件和原型所使用的建構式只有名稱相同而已,實際上是位於不同記憶體位置的建構式。
以過去學習的經驗,這算是設計上的小巧思
有時像設計第三方套件時
為了要避免"汙染全局"的屬性或方法
會用這種方式去隔開
以避免直接覆蓋掉原屬性方法
感謝回答。
確實如此,可惜無法重現 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
的實例?