我們知道,雖然JavaScript是基於對象(object-based)的語言。但是使用其原形(prototype)特性,我們完全可以實現十分sexy的OO編成架構,這個可以看看經典論壇的文章'基本上實現 javascript 的 OOP (0423版)'。
不過雖然我們實現了'類'這種概念,可是JavaScript的指令碼系統卻仍然是不認賬的。我們並沒有辦法使用指令碼系統中的typeof方法擷取自訂類的類型,比如'類'JSClass定義如下:
function JSClass()
{
this.Attribute1 = null;
this.Attribute2 = null;
this.Method1 = function()
{
// ...
};
this.Method2 = function()
{
// ...
};
this.toString = function()
{
return '[class JSClass]';
};
}
我們產生一個它的執行個體:var jsclass = new JSClass();
可是如果使用alert(typeof(jsclass)),我們只能得到'object'。而是用alert(jsclass),我們卻得到'[class JSClass]',這是對象執行個體預設調用toString()方法的結果。當然我們可以把類名稱"JSClass"使用toString()方法來返回,不過這種依賴手動type來保證正確性的方法並不時很理想。
於是我們從類定義本身去想辦法,由於JavaScript中的對象(Object)預設都實現了toString()方法,而且函數對象(Function)的toString()方法就是返回該函數的定義本身,這樣我們就可以通過處理類定義來擷取類名了。
我們通過對象執行個體的constructor屬性,可以擷取其建構函式的定義,而建構函式的名字也就是JavaScript使用者自訂類的類名稱。對於上面的例子,執行 var strFun = jaclass.constructor.toString(),strFun就是建構函式的原始語句定義(和上面語句塊內容相同)的字串。我們從strFun中取出"函數名"(類名)就行了,可是這裡需要注意。Function類的執行個體執行toString()時並不會格式化代碼,比如我們把JSClass的建構函式寫成如下格式:
function
JSClass
(
)
{
this.Attribute1 = null;
this.Attribute2 = null;
// ...
}
執行toString()後的strFun裡代碼也是這個樣子。
所以擷取類名還需要特別的小心,方法__typeof__的代碼如下:
function __typeof__(objClass)
{
if ( objClass && objClass.constructor )
{
var strFun = objClass.constructor.toString();
var className = strFun.substr(0, strFun.indexOf('('));
className = className.replace('function', '');
return className.replace(/(^\s*)|(\s*$)/ig, '');
}
return typeof(objClass);
}
樣本:
<script language="javascript">
alert(__typeof__(jsclass));
alert(__typeof__(JSClass));
alert(__typeof__(1));
alert(__typeof__([]));
alert(__typeof__({}));
</script>
結果分別為:"JSClass", "Function", "Number", "Array"和"Object"。
這裡需要注意兩個地方,一是:jsclass和JSClass的區別,jsclass是類執行個體,而JSClass傳回型別卻是Function哦;第二個是如果是系統類別型,使用typeof得到的類型都是小寫,比如number、array或objece啥的,而使用__typeof__獲得的類型名稱是和其類型名匹配的,首字母都大寫。