当前位置: 首页 > 图文教程 > 网络编程 > Javascript > 用JScript实现VB.Net,C#的[委托Delegate]:

Javascript
JS 文件本身编码转换 图文教程
jQuery Ajax之$.get()方法和$.post()方法
jQuery Ajax之load()方法
JavaScript 核心参考教程 内置对象
JavaScript 核心参考教程 RegExp对象
javascript hashtable实现代码
百度留言本js 大家可以参考下
javascript 判断某年某月有多少天的实现代码 推荐
让iframe子窗体取父窗体地址栏参数(querystring)
jquery pagination插件实现无刷新分页代码
jQuery与javascript对照学习 获取父子前后元素 实现代码
通用javascript脚本函数库 方便开发
JQuery 绑定事件时传递参数的实现方法
支持IE,Firefox的javascript 日历控件
javascript 变速加数功能实现代码
extjs 学习笔记(一) 一些基础知识
extjs 学习笔记(二) Ext.Element类
Jquery 学习笔记(一)
一些技巧性实用js代码小结
jquery 常用操作整理 基础入门篇

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


出处:互联网   整理: 软晨网(RuanChen.com)   发布: 2009-08-10   浏览: 225 ::
收藏到网摘: n/a

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


By:
[Lostinet{[email protected];[email protected]}]
[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+"\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.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);
}

 

 

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

 

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