js原生原型

原生原型

原生構造函數有自己的 .prototype 對象,如 Array.prototype、String.prototype 等。

這些對象包含其對應子類型所特有的行為特徵。

例如,將字符串值封裝為字符串對象之後,就能訪問 String.prototype 中定義的方法。

  • String#indexOf(..)
  • String#charAt(..)
  • String#substr(..)、String#substring(..) 和 String#slice(..)
  • String#toUpperCase() 和 String#toLowerCase()
  • String#trim()

以上方法並不改變原字符串的值,而是返回一個新字符串。

藉助原型代理(prototype delegatio),所有字符串都可以訪問這些方法:

js原生原型

其他構造函數的原型包含它們各自類型所特有的行為特徵,比如 Number#tofixed(..)(將 數字轉換為指定長度的整數字符串)和 Array#concat(..)(合併數組)。所有的函數都可以 調用 Function.prototype 中的 apply(..)、call(..) 和 bind(..)。

然而,有些原生原型(native prototype)並非普通對象那麼簡單:

typeof Function.prototype; // "function"

Function.prototype(); // 空函數!

RegExp.prototype.toString(); // "/(?:)/"——空正則表達式

"abc".match( RegExp.prototype ); // [""]

更糟糕的是,我們甚至可以修改它們(而不僅僅是添加屬性):

Array.isArray( Array.prototype ); // true

Array.prototype.push( 1, 2, 3 ); // 3

Array.prototype; // [1,2,3]

// 需要將Array.prototype設置回空,否則會導致問題!

Array.prototype.length = 0;

這裡,Function.prototype 是一個函數,RegExp.prototype 是一個正則表達式,而 Array. prototype 是一個數組。是不是很有意思?

將原型作為默認值

Function.prototype 是一個空函數,RegExp.prototype 是一個“空”的正則表達式(無 任何匹配),而 Array.prototype 是一個空數組。對未賦值的變量來說,它們是很好的默 認值。

js原生原型

這種方法的一個好處是 .prototypes 已被創建並且僅創建一次。相反,如果將 []、 function(){} 和 /(?:)/ 作為默認值,則每次調用 isThisCool(..) 時它們都會被創建一次 (具體創建與否取決於 JavaScript 引擎,稍後它們可能會被垃圾回收),這樣無疑會造成內 存和 CPU 資源的浪費。

另外需要注意的一點是,如果默認值隨後會被更改,那就不要使用 Array.prototype。上例 中的 vals 是作為只讀變量來使用,更改 vals 實際上就是更改 Array.prototype,而這樣會 導致前面提到過的一系列問題!


分享到:


相關文章: