WEB开发网
开发学院网页设计JavaScript 用JScript实现VB.Net,C#的[委托Delegate]: 阅读

用JScript实现VB.Net,C#的[委托Delegate]:

 2007-11-27 17:20:14 来源:WEB开发网   
核心提示:用JScript实现VB.net,C#的[委托Delegate]:By:[Lostinet{lostinet@21cn.com;lostinet@chongjian.com}][Sun Mar 17 UTC+0800 2002]VB.net,C#的委托把对象和方法封装在一个对象内,今天基于JScri

用JScript实现VB.net,C#的[委托Delegate]:


By:
[Lostinet{lostinet@21cn.com;lostinet@chongjian.com}]
[Sun Mar 17 UTC+0800 2002]


VB.net,C#的委托把对象和方法封装在一个对象内。
今天基于JScript的语法特点,也相应做了类似的功能。


不足之处:
如果Function不是Object的成员,Object必须允许填加新的属性。
 例如JScript的对象,DHTML DOM的window,document等;
 不行例如有new ActiveXObject(Microsoft.xml(标准化越来越近了)DOM)
如果Function不是Object的成员,在Function调用的时候,必须为Object填加一个
var theIndex=delegate function +new Date()+ +Math.random();
 => Object[theIndex]=Function
所以在for(var i in Object)的结构中,theIndex也会出现。


注意事项:
一旦delegate被引用,那么相关的object,function就不会被释放。
要完全释放object,function,必须先释放相关的delegate


脚本和解释如下:



//返回FunctionSelf的调用者,任何函数调用FunctionSelf将返回该函数本身
function FunctionSelf(){return FunctionSelf.caller}
/*
返回封装了obj,func的delegate
例如已知对象和函数:obj1.func1
那么调用obj1.func1(1,2,3)
和调用Delegate(obj1,obj1.func1)(1,2,3)
将会是相似的(除了上面提及的不足之处)


除了这个函数是公开的,其他函数不应该擅自调用。
obj :指定对象
funcOrIndex :指定函数的引用,或者是属于obj的一个名字
*/
function Delegate(obj,funcOrIndex)
{
 var delegate=new Function(,FunctionSelf().Call(FunctionSelf().arguments));
 delegate.Object=obj;
 delegate.Call=Delegate.Call;
 if(typeof(funcOrIndex)==string)
 {
 delegate.Index=funcOrIndex;
 delegate.Function=obj[funcOrIndex];
 }
 else
 {
 delegate.Index=null;
 delegate.Function=funcOrIndex;
 }
 if(typeof(delegate.Function)!=function)throw(没有指定函数!);
 return delegate;
}
//当delegate被调用时,这个函数就会被调用。
function Delegate.Call(arguments)
{
 /*
 涉及到function.arguments允许动态的个数,所以选择了eval来执行。
 当一个delegate被调用时,有全局的变量代表了当前被封装的Object,Function,Arguments的集合,
 以便被eval调用
 */
 //压入当前的delegate的情况
 Delegate.Stack.Push(this,arguments);
 var strArguments=;
 for(var i=0;i<arguments.length;i++)
 {
 strArguments+=Delegate.Stack().Arguments[+i+];
 if(i<arguments.length-1)strArguments+=,;
 }
 if(this.Index)
 var theIndex=this.Index;
 else
 {
 var theIndex=delegate function +new Date()+ +Math.random();
 this.Object[theIndex]=this.Function;
 }
 var strEval=Delegate.Stack().Delegate.Object[\+theIndex+\](+strArguments+);;
 try//运行delegate,释放当前的delegate的情况
 {
 eval(strEval);
 }
 catch(x)
 {
 //exception的发生可以返回。


 //当delegate被嵌套调用时,
 //如果中途没有被处理。那么就会返回到最外层
 if(!this.Index)delete this.Object[theIndex];
 Delegate.Stack.Pop(this);
 throw(x);
 }
 if(!this.Index)delete this.Object[theIndex];//如果是自定义的Index,那么就要删除
 Delegate.Stack.Pop();
}
//新建一个全局使用的变量
function Delegate.StackObject(delegate,arguments)
{
 this.Delegate=delegate;
 this.Arguments=arguments;
}
//返回堆栈当前的对象
function Delegate.Stack()
{
 return Delegate.Stack.Object;
}
//Stack的数据
function Delegate.Stack.Array(){}
//因为调用是堆栈形式的,所以数据也是堆栈的。
//压入当前delegate调用的状态。
function Delegate.Stack.Push(delegate,arguments)
{
 if(typeof(Delegate.Stack.Position)==undefined)Delegate.Stack.Position=-1;
 Delegate.Stack.Position++;
 Delegate.Stack.Object=new Delegate.StackObject(delegate,arguments);
 Delegate.Stack.Array[Delegate.Stack.Position]=Delegate.Stack.Object; 
}
//Release
function Delegate.Stack.Pop()
{
 Delegate.Stack.Array[Delegate.Stack.Position]=null;
 Delegate.Stack.Position--;
}



//下面、是例子:


function myalert(str)
{
 try{WScript.Echo(str)}catch(x){}
 try{alert(str)}catch(x){}
}


var obj=new Object();
obj.value=the obj.value :);
function func(a,b,c)
{
 var str=;
 var count=0;
 for(var i in this)
 {
 count++;
 str+=i+:+typeof(this[i])+\n;
 }
 var str=a,b,c=+a+:+b+:+c+\nthis.value=+this.value+\n+count+\n+str;
 myalert(str);
}
var delegate=Delegate(obj,func);//传递函数引用
delegate(3,33,333);
obj.callthefunc=func;//或者是:obj[callthefunc]=func;
delegate=Delegate(obj,callthefunc);//传递名字
delegate(4,5,6);


var xml(标准化越来越近了)=new ActiveXObject(Microsoft.xml(标准化越来越近了)DOM);
var xml(标准化越来越近了)o=new Object();
xml(标准化越来越近了)o.xml(标准化越来越近了)=xml(标准化越来越近了);
xml(标准化越来越近了)o.name=xml(标准化越来越近了)o;
xml(标准化越来越近了).onreadystatechange=Delegate(xml(标准化越来越近了)o,onreadystatechange);
xml(标准化越来越近了).load(test1.xml(标准化越来越近了));



var xml(标准化越来越近了)2=new ActiveXObject(Microsoft.xml(标准化越来越近了)DOM);
var xml(标准化越来越近了)o2=new Object();
xml(标准化越来越近了)o2.xml(标准化越来越近了)=xml(标准化越来越近了)2;
xml(标准化越来越近了)o2.name=xml(标准化越来越近了)o2;
xml(标准化越来越近了)2.onreadystatechange=Delegate(xml(标准化越来越近了)o2,onreadystatechange);
xml(标准化越来越近了)2.load(test2.xml(标准化越来越近了));



function onreadystatechange()
{
 if(this.xml(标准化越来越近了).readyState!=4)return;//not ready
 if(this.xml(标准化越来越近了).parseError.errorCode)
 myalert(this.name+this.xml(标准化越来越近了).parseError.reason);
 else
 myalert(this.xml(标准化越来越近了).xml(标准化越来越近了));
}

---------------2002.3.8:-------------

function FunctionSelf(){return FunctionSelf.caller;}
function Delegate(obj,funcOrName)
{
 var delegate=new Function(,return FunctionSelf().Invoke(FunctionSelf().arguments));

 delegate.Arguments=new Array();
 delegate.Object=obj;
 delegate.UniqueName=DelegateUniqueID+Math.floor((new Date().getTime()+Math.random())*1000);
 if(typeof(funcOrName)==string)
 {
 delegate.FuncName=funcOrName;
 delegate.Function=obj[delegate.FuncName];
 }
 else
 {
 delegate.FuncName=null;
 delegate.Function=funcOrName;
 }

 delegate.Invoke=Delegate.Invoke;
 delegate.Detach=Delegate.Detach;
 delegate.SetArguments=Delegate.SetArguments;
 delegate.PreInvoke=Delegate.PreInvoke;
 delegate.valueOf=new Function(,return \+delegate.UniqueName+\);
 delegate.toString=new Function(,return \+delegate.UniqueName+\);

 return delegate;
}
function Delegate.GetCaller()
{
 var cid=FunctionSelf().caller.caller.CallID;
 return Delegate.Coll[cid];
}
function Delegate.GetDelegate()
{
 var cid=FunctionSelf().caller.caller.CallID;
 return Delegate.Coll[cid].Delegate;
}
function Delegate.PreInvoke()
{
 this.SetArguments(Delegate.PreInvoke.arguments);
 return this;
}
function Delegate.SetArguments(args)
{
 if(args==null)args=new Array();
 this.Arguments=new Array();
 for(var i=0;i<args.length;i++)this.Arguments[i]=args[i];
 return this;
}
function Delegate.Invoke(args)
{
 if(this.Object==null)return;
 var cid=Delegate.Coll.Insert(this,args);
 var strArguments=;
 var i=0;
 for(i=0;i<args.length;i++)
 {
 strArguments+=Delegate.Coll[+cid+].Arguments[+i+];
 if(i<args.length-1)strArguments+=,;
 }
 if(i>0&&i<this.Arguments.length)strArguments+=,;
 for(;i<this.Arguments.length;i++)
 {
 strArguments+=Delegate.Coll[+cid+].Delegate.Arguments[+i+];
 if(i<this.Arguments.length-1)strArguments+=,;
 }

 var funcName=this.FuncName||cid;
 if(this.FuncName==null)this.Object[funcName]=this.Function;
 var res;
 var exception;
 try
 {
 res=eval(new Function(,\FunctionSelf().CallID=+cid+;return Delegate.Coll[+cid+].Delegate.Object[+funcName+](+strArguments+)\)());
 }catch(x){exception=x}
 if(this.Object&&(this.FuncName==null))delete this.Object[funcName];
 Delegate.Coll.Remove(cid);
 if(exception)throw(exception);
 return res;
}
function Delegate.Detach()
{
 this.Object=null;
 this.Function=null;
 this.FuncName=null;
 this.UniqueName=null;
}
function Delegate.EvalCaller(delegate,args,cid)
{
 this.Delegate=delegate;
 this.Arguments=args;
 this.CallID=cid;
}
function Delegate.Coll(){}
function Delegate.Coll.Insert(delegate,args)
{
 if(typeof(Delegate.Coll.Length)==undefined)Delegate.Coll.Length=0;
 Delegate.Coll.Length++;
 var cid=delegate.UniqueName+call+Math.floor((new Date().getTime()+Math.random())*1000);
 var EvalCaller=new Delegate.EvalCaller(delegate,args,cid);
 Delegate.Coll[cid]=EvalCaller;
 return cid;
}
function Delegate.Coll.Remove(cid)
{
 delete Delegate.Coll[cid];
 Delegate.Coll.Length--;
}

--------------------例子:

function myjoin()
{
 var str=;
 for(var i=0;i<myjoin.arguments.length;i++)
 str+=myjoin.arguments[i];
 return str;
}
alert(
 Delegate(new Object(),myjoin)
 .PreInvoke(1,2,3,4,5,6,7,8,9)
 .PreInvoke(a,b,c,d,e)
 (9,8,7,6)
);

---------------

Tags:JScript 实现 VB

编辑录入:coldstar [复制链接] [打 印]
赞助商链接