引用: http://blog.csdn.net/codemon/archive/2004/12/04/204398.aspx
首先我們簡單定義一個OO中關於繼承和重載定義的子集(不完整定義)
繼承 : 子類擁有其父類的方法和屬性
重載 : 子類可以重新定義從其父類繼承而來的方法 在C++ Class中的繼承和重載通過以下簡潔方式表現
class CParent //父類
{
public :
string str; //屬性
virtual void foo() {} //方法
};
class CChild :public CParent//子類,繼承
{
public:
virtaul void foo() { //重載
CParent::foo();//雖然重載了,還可以調用父類的方法,不過在父類的方法中的this卻是子類執行個體的指標哦
}
} 在JScript中要實現繼承和重載要繁瑣得多,要使用prototype 這些東東。那麼我們在JScript中有沒有簡單的方法可以類比這種效果?經過一番嘗試,我想出了一個還算簡潔的解決方案,沒考慮效率和實用性,給大家參考一下而已。
先說一下使用方法: <!--類比繼承和重載效果的指令碼庫-->
<SCRIPT LANGUAGE="jscript" src="
oop.htm"></SCRIPT>
<SCRIPT LANGUAGE="javascript">
<!--
function Parent()
{
Class(this); //使這個類從我們的最頂層的基類派生而來,類似於MFC中的類都從CObject派生呵呵,必須是第一條語句
this.str="Class Parent 的屬性值";
this.OutStr=function() { window.alert("Class Parent 的方法\t"+this.str); }
}
function Son()
{
Class(this); //同上,一定要有
this.Inherit(Parent); //繼承Parent
this.OutStr=function() { //重載Parent的OutStr方法
window.alert("Class Son 的方法\t"+this.str);
}
this.OutStr2=function(){
this.OutStr();//調用重載後的OutStr方法,實際上是Son的OutStr
this.Parent_OutStr();//調用父類Parent的OutStr方法
}
}
function Grandson()
{
Class(this);//同上
this.Inherit(Son);//繼承Son
this.str="Class Grandson的屬性值";
} var b=new Son();
var c=new Grandson();
b.OutStr();//輸出“Class Son的方法 Class Parent 的屬性值“,因為Son重載了Paren的OutStr方法但沒改變str屬性值
c.OutStr();//輸出“Class Son的方法 Class Grandson的屬性值“,因為Grandson沒有重載Son的OutStr方法但改變了str屬性值
b.Parent_OutStr(1,"str",window);//調用Parent的OutStr,輸出“Class Parent的方法 Class Parent 的屬性值“,因為Son沒改變str屬性值
c.Son_OutStr();//調用Son的OutStr,輸出“Class Son的方法 Class Grandson的屬性值“,因為Grandson改變了str屬性值
c.Son_Parent_OutStr();//調用Parent的OutStr,輸出“Class Parent的方法 Class Grandson的屬性值“,因為Grandson改變了str屬性值
b.OutStr2();
window.alert(c.Tree());//顯示c的繼承關係圖
window.alert(c.MembersMap());//顯示c的方法和屬性
//-->
</SCRIPT> 下面把oop.htm的原始碼貼出來大家有興趣參考一下:) //這是個指令檔,請用<SCRIPT LANGUAGE=jscript src="oop.htm"></SCRIPT>的方式使用
//<SCRIPT LANGUAGE=javascript>
/////////////common function///////////////////////
//取得函數對象的名稱,返回字串
function FunctionName(f)
{
if(typeof(f)=="function"){
var pn=new String(f);
var n=pn.indexOf("(",0);
pn=pn.substring(0,n);
pn=pn.replace(/^[ \f\v\t\b\n\r]*/g,"");
pn=pn.replace(/^function/g,"");
pn=pn.replace(/^[ \f\v\t\b\n\r]*/g,"");
pn=pn.replace(/[ \f\v\t\b\n\r]*$/g,"");
return pn;
}
return "";
}
///////////////////////////////////////////////////////
//基類
function JSClass()
{
//取得類名,返回字串
this.ClassName=function() { return FunctionName(this.constructor); }
//指定繼承_base類,可以帶基類初始化參數如this.Inherit(classBase,param1,param2,param3);
//返回true或false
this.Inherit=function(_base)
{
//檢驗_base是合法類而且尚未繼承_base類
if(typeof(_base)=="function" && !this.IsMyParent(_base))
{
//如此函數是在頂層執行個體構造(即直接用new產生執行個體)時調用,isRoot為true
//如此函數是在嵌套派生(即在Inherit中調用基類)時嵌套調用,isRoot為false
var isRoot=(this.constructor==this.Inherit.caller);
this.___super=_base;
//帶參數初始化基類
var callString="";
for(i=1;i<arguments.length;i++){
if(i>1) callString+=",";
callString+="arguments["+i+"]";
}
eval("this.___super("+ callString +");");
this.___super=null; if(isRoot)//如果是頂層執行個體
{
//{{{如不需要調用IsMyParent和調用基類的方法及工具函數可去掉以下代碼
eval("this.___super=new _base(" + callString + ");");//產生基類的執行個體
Class(this.___super);//保證基類是JSClass的衍生類別
var pn=this.___super.ClassName();
for(key in this.___super){
if((!this.IsKeyWord(key)) && typeof(this.___super[key])=="function"){//不要前面帶"___"的函數和保留函數
eval("this."+ pn + "_" + key + "=this.___super[\"" + key + "\"]");//儲存基類方法使之可用this.基類名_基類方法的方式使用
}
}
var pr=this.Parents();
pr[pn]=this.___super.Parents();//將基類的派生關係數組添加到本類的派生關係數組中
pr.length++;
this.___super=null;
//}}}
}
return true;
}
return false;
}
//tool Method
//判斷是否是自己的直接父類,返回true或false
this.IsMyParent=function(obj)
{
var objn="";
var ps=this.Parents();
if(isClass(obj)) objn=obj.ClassName();
else if(typeof(obj)=="function") objn=FunctionName(obj);
if(objn!="") return (typeof(ps[objn])=="object");
else return false;
}
//取派生關係數組,返回Array
this.Parents=function(){
if(!(this.___parents instanceof Array)) this.___parents=new Array();
return this.___parents;
}
//產生類的繼承關係圖,返回字串
this.Tree=function() { return ClassTree(this); }
//顯示類的結構,返回字串
this.MembersMap=function() { return ClassMembers(this); }
//取得所有的方法名稱,返回一個字串數組
this.Methods=function()
{
var methodArr=new Array();
for(key in this){
if(typeof(this[key])=="function" && (!this.IsKeyWord(key))) methodArr.push(key);
}
return methodArr;
}
//取得所有的屬性名稱,返回一個字串數組
this.Properties=function()
{
var PropArr=new Array();
for(key in this){
if(typeof(this[key])!="function" && (!this.IsKeyWord(key))) PropArr.push(key);
}
return PropArr;
}
this.IsKeyWord=function(str)//是否是保留關鍵字
{
var s=new String("" + str);
if(s.indexOf("___",0)==0) return true;
var o=new JSClass();
if(typeof(o[s])=="function") return true
return false;
}
}
//////////
tools funciton////////////////////////
//使一個類是JSClass的衍生類別
function Class(o)
{
if(typeof(o)=="object" && typeof(o.constructor)=="function" ) {
o.___class=JSClass;
o.___class();
return true;
}
return false;
} //判斷一個類是否JSClass的衍生類別
function isClass(o)
{
if(typeof(o)=="object" && typeof(o.constructor)=="function" ) {
if(typeof(o.___class)=="function" && o.___class===JSClass) return true;
}
return false;
} //產生JSClass類的繼承關係圖,返回字串
function ClassTree(jscObject)
{
var outputStr="";
function ___dump(objName,parentList,preString,isLast,InheritLevel)
{
var i=0;
if(InheritLevel>32) outputStr+=preString+"__"+objName+" ......\n";
else outputStr+=preString+"__"+objName+"\n";
if(parentList.length>0)
{
var newPreString=new String(preString);
if(isLast) newPreString=newPreString.replace(/[|]$/i,"");
newPreString+=" |";
i=0;
for(key in parentList) {
___dump(key,parentList[key],newPreString,(i==parentList.length-1),InheritLevel+1);
i++;
}
}
}
if(isClass(jscObject)) ___dump(jscObject.ClassName(),jscObject.Parents(),"",false,0);
else outputStr="NOT_JSCLASS_OBJECT";
return outputStr;
} //顯示JSClass類的結構,,返回字串
function ClassMembers(jscObject)
{
var outputStr="";
if(isClass(jscObject))
{
outputStr+="class " + jscObject.ClassName() + "\n";
var m=jscObject.Methods();
var p=jscObject.Properties();
outputStr+="\n Methods\n";
for(key in m) { outputStr+=" |__ "+m[key]+"\n"; }
outputStr+="\n Properties\n";
for(key in p) { outputStr+=" |__ "+p[key]+"\n"; }
}
else outputStr="NOT_JSCLASS_OBJECT";
return outputStr;
}
//</SCRIPT>