相信很多人應該都有想對瀏覽器 JavaScript引擎

所提供的原生類別 (例如 Object、Array、String) 與物件擴充

原則上大部分只需要增加 function (method) 即可

但是要達成目的有些問題是要注意的


 

問題

1. 為什麼不用 JavaScript OO強化模組建立擴充模組?

JavaScript OO強化模組雖有提供繼承能力

但是繼承原生類別所建立的模組卻有先天缺陷

原因在於部分原生類別 (function) 的 function只接受該類別建立的物件呼叫

即使是繼承該類別的子類別亦不可

否則就會接到錯誤例外 (Error Exception) 無法執行

因此僅有針對該類別的原型 (prototype) 作擴充一途

實驗:

P = new Date();
function Test(){};
Test.prototype = P;
T = new Test();
T.getDate();  // Error

 

2. 對原生類別擴充新成員的時候會如何?

如果有使用過 for each迴圈

JavaScript中語法 for (attrName in object) { ... }

應該會知道 for each迴圈會將物件中的所有成員列舉出來

在 JavaScript中,不管成員的值是什麼都算是成員

但像是陣列 (Array) 物件含有許多 method

例如 slice、sort,都是 Array 的成員

但使用 for each迴圈的時候卻都不會被列舉

又例如 Object 也有許多的成員 function,也不會被列舉出來

這是因為原生類別幾乎所有固定成員

幾乎都被設定為不可列舉 (non-enumerable)

因此 for each迴圈就不會將這些成員列舉

如果對原生物件增加新成員,新成員卻不會被認為是不可列舉的

這就會造成非常大的影響

尤其現在許多應用當中會直接使用 Object物件

並且對這些物件使用 for each迴圈對成員做一致性處理

原本並不預期會出現的成員,卻因為新成員加入而擾亂

致使程式出現意料不到的錯誤

 

3. 擴充成員名稱與原有名稱相同應該如何?

基本上會使用這樣的方式

大概都是希望對原有的 function作擴充

不過這樣的方式在 JavaScript當中做起來是很麻煩的

因為開發者必須要先儲存舊 function在變數中

接著在新 function中,使用這個舊 function

但要注意的是,因為舊 function已經和物件斷開連結了

因此必須要用  functoin.call 或 function.apply 呼叫

多了,程式碼會變得稍微難管理


解法

雖然說 JavaScript OO 強化模組可能不適用

但是其中的 function繼承技術還是可以拿出來用的

本文提供的解法就借用了 OO 強化模組當中的一部份

解決名稱衝突的問題,但是還有一點要注意的是

有時候只是為了補足瀏覽器平台太舊而沒有新版本提供的 function

在這情況下,並不希望將原生的 function取代掉

例如 Object.keys,Array.prototype.indexOf 等

但是另一個解法是對 jQuery做函式擴充

端看開發人員喜歡哪一種語言表示法

但是也要注意的是,如果擴充了太常使用的成員名稱

而與其他模組衝突,程式運作出問題仍是無法避免的

( 例如 jQuery-DataTable 插件,對 Object 新增 toArray

若是自行擴充 toArray,會對該插件運作產生嚴重錯誤 )

 

有時候並不只針對 prototype擴充

而會針對這個類別本身進行擴充

例如前述的 Object.keys

因此本文提供的解法當中可以設定一些擴充用參數

來達成多種目的

 

為了解決for each迴圈的成員列舉問題

當中使用了 Object.defineProperty 設定成員的列舉特性

但是需要注意的是 Object.defineProperty

在 IE瀏覽器當中,必須要 9以上才能運作

( IE 8雖有提供,但是僅針對 HTML DOM物件設定 )

所以本模組有 IE 瀏覽器瀏覽模式必須 9以上的限制


 

程式碼

因為當中沒用到太艱深的技術

關鍵部分也是抄過來,使用限制目前也算多

提供上來讓大家參考,看是否有人有其他好想法

點擊這裡觀看

當中除了擴充功能外,亦針對部分原生物件做了擴充

 

Remark

1. 2015/09/18,新增 String.prototype.substr 功能擴增

arrow
arrow

    wylokgo101 發表在 痞客邦 留言(0) 人氣()