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

Javascript
IE bug table元素的innerHTML
Javascript学习笔记1 数据类型
Javascript学习笔记2 函数
Javascript学习笔记3 作用域
Javascript学习笔记4 Eval函数
Javascript学习笔记5 类和对象
Javascript学习笔记6 prototype的提出
Javascript学习笔记7 原型链的原理
Javascript学习笔记8 用JSON做原型
Javascript学习笔记9 prototype封装继承
Javascript 读书笔记索引贴
JavaScript 事件冒泡应用实例分析
JavaScript 事件冒泡简介及应用
Extjs学习笔记之九 数据模型(上)
javascript Object与Function使用
取选中的radio的值
JavaScript 学习笔记(九)call和apply方法
javascript下判断一个对象是否具有指定名称的属性的的代码
Javascript 实现TreeView CheckBox全选效果
jquery插件 cluetip 关键词注释

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


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

 

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