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

Lostinet 2002-03-17 07:15:40
用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.XMLDOM")
如果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+"\nobj.value="+obj.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.XMLDOM");
var xmlo=new Object();
xmlo.xml=xml;
xmlo.name="xmlo";
xml.onreadystatechange=Delegate(xmlo,onreadystatechange);
xml.load("test1.xml");


var xml2=new ActiveXObject("Microsoft.XMLDOM");
var xmlo2=new Object();
xmlo2.xml=xml2;
xmlo2.name="xmlo2";
xml2.onreadystatechange=Delegate(xmlo2,onreadystatechange);
xml2.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);
}
...全文
37 4 打赏 收藏 转发到动态 举报
写回复
用AI写文章
4 条回复
切换为时间正序
请发表友善的回复…
发表回复
songzx66 2002-03-18
  • 打赏
  • 举报
回复
test
Lostinet 2002-03-18
  • 打赏
  • 举报
回复
今天写的:

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

delegate.Invoke=Delegate.Invoke;
delegate.Detach=Delegate.Detach;

delegate.Arguments=Delegate.arguments;
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;
}
return delegate;
}
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+=",";
}
i+=2;
if(i>2&&i<this.Arguments.length)strArguments+=",";
for(;i>1&&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("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)
{
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];
}
UserR 2002-03-17
  • 打赏
  • 举报
回复
收到
Lostinet 2002-03-17
  • 打赏
  • 举报
回复
例子中的
var str="a,b,c="+a+":"+b+":"+c+"\nobj.value="+obj.value+"\n"+count+"\n"+str;
有错,不足说名Delegate的用途,
应该是:

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);
}

28,405

社区成员

发帖
与我相关
我的任务
社区描述
ASP即Active Server Pages,是Microsoft公司开发的服务器端脚本环境。
社区管理员
  • ASP
  • 无·法
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧