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

Javascript
JavaScript 拖拽实现(附注释),最经典简单短小精悍!
学习drag and drop js实现代码经典之作
jquery创建div 实现代码
jquery遍历input取得input的name
jQuery 对象中的类数组操作
js 发个判断字符串是否为符合标准的函数
细品javascript 寻址,闭包,对象模型和相关问题
在IE上直接编辑网页内容的js代码(IE地址栏js)
一个选择最快的服务器转向代码
JQUERY 对象与DOM对象之转换
javascript 对象比较实现代码
jquery 获取json数据实现代码
Firefox div高度自适应
xml和web特殊字符
js 表单验证方法(实用)
ie和firefox不兼容的解决方法集合
js 数组操作代码集锦
js checkbox(复选框) 使用集锦
JS 判断代码全收集
理解JavaScript的caller,callee,call,apply

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


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

 

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