VBS与JS变量共享与互操作
<Job id="VBS_JS_CallEachOther_Test"> <comment id="note.all"> 1.支持跨语言的变量、函数、过程; 1.1VBS所有的数字类型自动转换为JS的Number类型; 1.2VBS数组,在JS中自动包装为VBArray对象,类型为unknown;可用其toArray方法转换为JS的数组 1.3VBS类型=>JS类型: Byte/Integer/Long/Single/Double/Currency/Decimal=>Number; Array=>unknown;Nothing/Null/COMObject=>Object;Date=>Date; 1.4JS类型=>VBS类型: null=>Null;NaN=>Double;Number(整数)=>Long;Number(浮点数)=>Double; Array/Date/Error/Object/Function/RegExp/ClassObject=>JScriptTypeInfo COMObject=>COMObject[如new ActiveXObject('Scripting.FileSystemObject')=>FileSystemObject] 1.5VBS类型<=>JS类型: Boolean<=>Boolean;String<=>String;Empty<=>undefined 1.6VBS的Date类型,共享到JS中也是Date类型,但是在JS中无法按照原生的JS Date对象一样对其进行操作 2.不支持跨语言类,但支持跨语言类对象变量 3.所有的由JS代码中定义后转换到VBS中的JScriptTypeInfo类型变量,都可以原样访问在JS中定义的 属性/方法 4.JS数组共享到VBS中表现为JScriptTypeInfo类型,但无法简易地对其进行元素读写操作,要进行此类操作 请先将它转换成VBS的数组后,再对新数组进行读写 5.VB6/VBA中借助MSScriptControl,与JS数据结构进行互操作的规则,与这里的VBS大同小异;VB6/VBA中有 CallByName函数,可以通过如CallByName(js_arr,"0",vbGet)这样的形式来直接读取数组元素;修改元素 则是使用CallByName(js_arr,"0",vbLet/vbSet,newValue);VB6/VBA中JScriptTypeInfo类型变量的一切
操作都只能通过CallByName来进行,这方面比VBS麻烦 </comment> <script id="global" language="JScript"> var alert=function(){ var result=''; for(var i=0;i<arguments.length;i++) result=result+arguments[i]+', '; WScript.Echo(result.slice(0,-2)); } </script> <script id="vbs.test" language="VBScript"> Dim vbs_arr,vbs_int,vbs_single,vbs_str Dim vbs_bool,vbs_empty,vbs_circle,vbs_date Dim vbs_err vbs_arr=Array(1,2,3) vbs_int=3 vbs_single=3.25 vbs_str="vbs_str" vbs_bool=True vbs_empty=Empty Function vbs_func(a,b) vbs_func=a+b End Function Sub vbs_sub(a,b) alert typename(a),typename(b) End Sub Class Circle Private D_ Public D_History Public Property Get D() D=D_ End Property Public Property Let D(Value) D_=Value D_History=D_History & Value & ", " End Property Public Function GetArea() GetArea=4*Atn(1)*Me.D^2 end function Private Sub Class_Initialize WScript.Echo "Circle Object Initialized!!!" End Sub Private Sub Class_Terminate WScript.Echo "Circle Object Terminated!!!" End Sub End Class Set vbs_circle=New Circle vbs_date=Now on error resume next err.raise 6 '溢出错误 'set vbs_err=new ErrObject '用Err/ErrObject/Error都无法创建VBS的错误对象 set vbs_err=Err 'err.Clear 'vbs_err与err是同一个对象,所以为后面的试验,这里最好注销 </script> <script id="js.test" language="JScript"> var js_arr=[1,2,3]; var js_int=3,js_single=3.2,js_double=3.2324242432424; function js_func(a,b){ alert(typeof a,typeof b); } var js_str='hello world'; var js_bool=true; var js_undefined=undefined; function Square(Length){ this.Length=Length; this.GetArea=function(){ return this.Length*this.Length; } } var js_square=new Square(5); var js_date=new Date(); var js_err=new Error(146250,'what the fuck are you doing?'); </script> <script id="js.main" language="JScript"> (function JS_VBS_TEST(){ //1.同一个域里面的VBS数组在JS代码块中是可见的,其类型是unknow, // 实际是VBArray,可使用VBArray.toArray()将其转换为JS数组 alert("typeof vbs_arr",typeof vbs_arr); alert("vbs_arr.toArray()",vbs_arr.toArray()); //2.同一个域里面的VBS数字类型的变量在JS代码块中也是可见的,其 // 类型一律是number alert("typeof vbs_int",typeof vbs_int); alert("vbs_int",vbs_int); alert("typeof vbs_single",typeof vbs_single); alert("vbs_single",vbs_single); //3.同一个域里面的VBS函数/过程在JS代码块中也是可见的,其类型 // 一律是unknown,无法直接转换为JS函数,但是可以直接调用;无 // 法以apply的方式来调用; alert("typeof vbs_func",typeof vbs_func); alert("vbs_func(3,6)",vbs_func(3,6)); //alert("vbs_func.apply(undefined,[3,6])",vbs_func.apply(undefined,[3,6])); alert("typeof vbs_sub",typeof vbs_sub); alert("vbs_sub(3,undefined)",vbs_sub(3,undefined)); alert("vbs_sub([1,2],/\w+/g)",vbs_sub([1,2],/\w+/g)); alert("vbs_sub(3.7293,null)",vbs_sub(3.7293,null)); alert("vbs_sub(new Date(),NaN)",vbs_sub(new Date(),NaN)); alert("vbs_sub('hello',true)",vbs_sub("hello",true)); alert("vbs_sub(new Error(3),3.56790456909656789)", vbs_sub(new Error(3),3.56790456909656789)); alert("vbs_sub({},function add(){})",vbs_sub({},function add(){})); alert("vbs_sub(new Object(),new Square())",vbs_sub(new Object(),new Square())); alert("vbs_sub(Math,new ActiveXObject('Scripting.FileSystemObject'))", vbs_sub(Math,new ActiveXObject('Scripting.FileSystemObject'))); //4.同一个域里面的VBS字符串类型的变量在JS代码块中也是可见的,其 // 类型是string,与JS字符串是互通的,JS的字符串方法都可以直接用 alert("typeof vbs_str",typeof vbs_str); alert("vbs_str",vbs_str); alert("vbs_str.toUpperCase()",vbs_str.toUpperCase()); //5.同一个域里面的VBS布尔类型的变量在JS代码块中也是可见的,其 // 类型是boolean,与JS的布尔类型是互通的 alert("typeof vbs_bool",typeof vbs_bool); alert("vbs_bool",vbs_bool); //6.同一个域里面的Empty类型的变量在JS代码块中也是可见的,其 // 类型是undefined,与JS的Undefined类型是互通的,调用VBS函数/过程 // 时在JS中传入undefined,在VBS函数/过程中接受到的将是Empty alert("typeof vbs_empty",typeof vbs_empty); alert("vbs_empty",vbs_empty); alert("vbs_func(3,6)",vbs_func(3,6)); //7.同一个域里面的类类型的变量在JS代码块中也是可见的,其类型是 // object,其方法/属性都可以正常访问,但是无法实现apply式调用;其公共的 // 方法属性可以使用for...in完成遍历,这些遍历到的索引可以用来进行 // 成员访问,其可访问方法的类型如一般的函数一样是unknown类型,所以 // 如果只是想要遍历属性和方法中的一者,就可以使用这个类型判定,来 // 获取对应的成员名列表 vbs_circle.D=10 alert(vbs_circle.D) alert("typeof vbs_circle",typeof vbs_circle); //object alert("vbs_circle.GetArea()",vbs_circle.GetArea()); //alert(vbs_circle.GetArea.apply(vbs_circle)); alert('for...in: '); for(var i in vbs_circle) if(typeof vbs_circle[i]=='unknown') alert('vbs_circle.'+i+'(...) = '+vbs_circle[i]()); else alert('vbs_circle.'+i+' = '+vbs_circle[i]); alert('read/write by property/method index: '); alert("vbs_circle['D'] = "+vbs_circle['D']); alert("vbs_circle['D_History'] = "+vbs_circle['D_History']); alert("vbs_circle['GetArea']() = "+vbs_circle['GetArea']()); alert("typeof vbs_circle['D']",typeof vbs_circle['D']); //number alert("typeof vbs_circle['D_History']",typeof vbs_circle['D_History']); //string alert("typeof vbs_circle['GetArea']",typeof vbs_circle['GetArea']); //unknown //var vc=new Circle(); //报错 //alert(typeof vc); //undefined vbs_circle=undefined; //会触发VBS对象的对象销毁事件 //8.同一个域里面的Date类型的变量在JS代码块中也是可见的,其 // 类型也是date,但是它不是JS的date对象 alert("typeof vbs_date",typeof vbs_date); //date alert("vbs_date",vbs_date); //alert(vbs_date.getYear()); //报错:为null或不是对象 var js_d=new Date(); alert("js_d.getYear()",js_d.getYear()); //9.同一个域里面的Err类型的变量在JS代码块中也是可见的,其 // 类型是object,成员不可遍历 alert("typeof vbs_err",typeof vbs_err); //object alert(vbs_err+':'+vbs_err.Description+','+vbs_err.Source); for(i in vbs_err) //不可遍历 alert(i); vbs_err.Clear(); alert(vbs_err+':'+vbs_err.Description+','+vbs_err.Source); })(); </script> <script id="vbs.main" language="VBScript"> WScript.Echo "==========================================================" Sub VBS_JS_TEST '1.同一个域里面的JS数组在VBS代码块中是可见的,其类型是JScriptTypeInfo, ' 但凡这种类型,其JS中原有定义的成员,都是可以原样访问的;数组通过索引 ' 取得元素,在这里会稍显麻烦,需要依赖循环,没有直接取得第N个元素的方法 ' 建议的方法是使用For Each循环将这个JScriptTypeInfo的数组转换为VBS的数组 ' 再进行读写元素的操作 alert "typename(js_arr)",typename(js_arr) alert "js_arr",js_arr alert "js_arr.slice(1)",js_arr.slice(1) alert "js_arr.length",js_arr.length alert "For Each:" Dim i For Each i in js_arr alert i Next '2.同一个域里面的JS数字类型的变量在VBS代码块中也是可见的,其 ' 类型由原数字是否是整数决定,如果是小数,在VBS中表现为Double类型 ' 如果是一个整数,在VBS中会表现为Long类型 alert "typename(js_int)",typename(js_int) alert "js_int",js_int alert "typename(js_single)",typename(js_single) alert "js_single",js_single '3.同一个域里面的JS函数在VBS代码块中也是可见的,其类型一律是 ' JScriptTypeInfo alert "typename(js_func)",typename(js_func) alert "js_func(3,3.2)",js_func(3,3.2) alert "js_func(CByte(3),CCur(50))",js_func(CByte(3),CCur(50)) alert "js_func(Array(1,2,3),Nothing)", _ js_func(Array(1,2,3),Nothing) alert "js_func(Empty,Null)",js_func(Empty,Null) Dim vbs_arr1() alert "js_func(Now,vbs_arr1)",js_func(Now,vbs_arr1) alert "js_func('hello',true)",js_func("hello",true) alert "js_func(Err,New Circle)",js_func(Err,New Circle) alert "js_func(CreateObject('Scripting.FileSystemObject'))", _ js_func(CreateObject("Scripting.FileSystemObject")) '4.同一个域里面的JS字符串类型的变量在VBS代码块中也是可见的,其 ' 类型是String,与VBS字符串是互通的,VBS的字符串函数都可以直接用 alert "typename(js_str)",typename(js_str) alert "js_str",js_str alert "UCase(js_str)",UCase(js_str) '5.同一个域里面的JS布尔类型的变量在VBS代码块中也是可见的,其 ' 类型是Boolean,与VBS的布尔类型是互通的 alert "typename(js_bool)",typename(js_bool) alert "js_bool",js_bool '6.同一个域里面的Undefined类型的变量在VBS代码块中也是可见的,其 ' 类型是Empty,与VBS的Empty类型是互通的,在调用JS的函数/方法 ' 时在VBS中传入Empty,在JS函数/方法中接受到的将是undefined alert "typename(js_undefined)",typename(js_undefined) WScript.Echo "js_undefined"+", "+js_undefined alert "js_undefined=Empty",js_undefined=Empty alert "js_func(3,Empty)",js_func(3,Empty) '7.同一个域里面的类类型的变量在VBS代码块中也是可见的,其类型是 ' JScriptTypeInfo,其原型定义的方法/属性都可以正常访问 js_square.Length=10 alert js_square.Length alert "typename(js_square)",typename(js_square) alert "js_square.GetArea()",js_square.GetArea() alert "js_square.GetArea.apply(js_square)",js_square.GetArea.apply(js_square) 'Set sq=New Square '报错 '8.同一个域里面的Date类型的变量在VBS代码块中也是可见的,其 ' 类型也是JScriptTypeInfo,其原型定义的方法/属性都可以正常访问 alert "typename(js_date)",typename(js_date) alert "js_date",js_date alert "js_date.getYear()",js_date.getYear() 'alert Month(js_date) '因为它不是VBS的Date类型,所以VBS的日期时间函数无法处理它 '9.同一个域里面的Error类型的变量在VBS代码块中也是可见的,其 ' 类型是JScriptTypeInfo,其原型定义的方法/属性都可以正常访问 alert "typename(js_err)",typename(js_err) alert js_err.Number & ":" & js_err.Description End Sub Call VBS_JS_TEST </script> </job>
这是一个wsf脚本,用记事本保存为wsf类型文本文件(比如wsf.wsf),即可运行,建议使用如下命令调用它(因为双击弹窗会很多,也不方便对比输出):
CScript //nologo wsf.wsf