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

Javascript
JS getMonth()日期函数的值域是0-11
jQuery 处理网页内容的实现代码
jQuery 树形结构的选择器
jQuery 处理表单元素的代码
JQuery 动画卷页 返回顶部 动画特效(兼容Chrome)
JavaScript 10件让人费解的事情
类似GMAIL的Ajax信息反馈显示
两个比较有用的Javascript工具函数代码
JavaScript Timer实现代码
JavaScript 学习技巧
JavaScript 题型问答有答案参考
js删除select中重复项的实现代码
javascript中的链式调用
JavaScript DOM学习第一章 W3C DOM简介
JavaScript DOM 学习第二章 编辑文本
JavaScript DOM 学习第三章 内容表格
JavaScript DOM学习第四章 getElementByTagNames
JavaScript DOM 学习第五章 表单简介
JavaScript DOM学习第六章 表单实例
JavaScript DOM 学习第七章 表单的扩展

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


出处:互联网   整理: 软晨网(RuanChen.com)   发布: 2009-08-10   浏览: 156 ::
收藏到网摘: 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)
);

 

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