http://www.blogjava.net/flyingis/archive/2006/09/12/69213.html
JavaScript 對象的反射及應用
作者:Flyingis
Java和.NET都有著比較完善的反射機制,用來處理未知的對象並擷取它們的屬性和方法。JavaScript雖然沒有完善的反射體系,但在編程的時候還是可以通過代碼設計來實作類別似反射的準系統。
檢測一個JavaScript對象是否支援某種特定的屬性或方法:
if (typeof(obj.property) != "undefined") {}
這樣聲明比直接使用"if (obj.property)"來描述要更準確,因為當obj.property的值為false、0、null的時候,雖然該屬性存在,但返回的結果卻恰恰相反。
如果要求檢測更詳細一些,查看該屬性的具體類型,可以用instanceof操作符:
if (obj instanceof PredefinedObj) {}
但是,當對obj對象進行條件檢測的時候,如果多種條件的物件類型存在繼承關係,則需要注意代碼的書寫順序,例如:
function() ExamineType(obj) {
if (obj instanceof Object) {
alert("An Object");
else if (obj instanceof Array) {
alert("An Array");
}
}
}
上述代碼執行的結果會認為原為Array類型的obj是一個Object,因為Array本身就是從Object繼承而來,顯然,將對Array的檢測放在前面會得到更精確的結果。因此,使用instanceof來判斷物件類型,需要注意當兩個對象存在繼承關係的時候,應該關注檢測順序的問題,進一步我們可以想到,JSON建立的對象不是Object就是Array,使用instanceof來檢測JSON對象意義不大。
利用JavaScript的反射,我們可以編寫一個函數來檢查對象是否有一個特定名稱的函數,然後利用該函數進行計算,以此在JavaScript中實現介面的功能,為在Ajax中使用設計模式奠定基礎。
//this.getWeight和this["getWeight"]意義相同
//判斷對象是否存在指定名稱的函數
Object.prototype.hasFunc = function(func) {
return this && this[func] && this[func] instanceof Function;
}
function hasWeight(obj) {
return obj.hasFunc("getWeight");
}
//判斷參數是否為數實值型別
function isNum(param) {
return parseFloat(param) != NaN;
}
//計算兩個對象的重量
function calWeight(obj1, obj2) {
var total = null;
if (hasWeight(obj1) && hasWeight(obj2)) {
var w1 = obj1.getWeight();
var w2 = obj2.getWeight();
if (isNum(w1) && isNum(w2)) {
total = parseFloat(w1) + parseFloat(w2);
}
}
return total;
}
calWeight先判斷兩個對象是否均存在getWeight()函數,然後檢查getWeight()計算結果是否為數實值型別,最後進行數值相加返回計算結果。需要注意的是,parseFloat(param)函數能夠除去param中非數字部分,如果param=16pm,parseFloat(16pm)得到的結果是16。如果不使用parseFloat(param)函數對getWeight()計算結果進行檢驗,那麼會帶來安全性的問題,這種情況下可以將對象的getWeight()設計為返回字串或其他類型,在調用它之前我們是不知道JavaScript函數的傳回型別的,因為JavaScript函數沒有預先定義的類型。