在公司一直负责一个界面引擎的模块的设计开发工作,主要使用XML和JavaScript两种技术。
最初我们使用的是MS的JS引擎(由IActiveScript及一些相关接口组成,下称MS-JS),后来由于一些问题,将MS-JS替换成Google才推出不久的JS引擎V8(下称V8-JS)。
MS-JS不知道多久没更新了,不过也还好用,文档写得也清楚。
V8-JS是Google的Chrome浏览器中的一个亮点,刚推出不久,还在不断更新中,性能据说比MS的高过不止一个数量级,还有很重要的一点是它开源,“源码之前,了无秘密”,不过要揭示这里面的秘密,也是要精通不少技术的,比如汇编语言、编译原理、C++模板、设计模式等等,这也难怪,毕竟这是个虚拟机嘛。本人所知也是略知皮毛,在项目中有了一些使用经验,和大家分享一下。
两者设计理念上有一些差异。MS-JS以COM接口的形式发布,引擎建立在IDispatch接口的基础之上,虽然效率上要吃些亏,但是实现了在二进制代码级别上的重用,以至于我们能到处看到MS-JS的身影,在IE浏览器中,在Windows Script Host中等等。我们还可以在各种不同的编程语言中使用它(COM的确是软件重用的一个成功典范)。V8-JS以C++库的形式发布,大概是因为V8-JS对性能的要求很高,而且主要在Chrome中的使用的缘故吧。
作为Javascript的运行环境,两者在使用方式大体上是相同的:宿主程序把自己的对象与JS对象绑定,解释Js脚本并执行,脚本代码在被执行的过程中访问对象的属性和方法,当宿主程序有事件发生时可调用脚本中相应的处理代码。在细节上两者的差别就比较大了,下面分别做些简短的讲述:
1.创建JS引擎(执行上下文)
MS-JS:
//用COM函数CoCreateInstance创建引擎对象
CComPtr
//创建脚本运行环境
HRESULT hr = ::CoCreateInstance(CLSID_JAVAScript, NULL, CLSCTX_INPROC, IID_IActiveScript, (void**)&activeScript);
//创建宿主对象,应用程序需实现IActiveScriptSite,通过IActiveScript的接口函数SetScriptSite与之关联,在第一次执
//行脚本的时候,引擎会向宿主接口查询名字对象的接口。
CComPtr
hr = activeScript->SetScriptSite(pSite);
//添加全局名字对象
AddNameItemToSrcipt(activeScript);//需实现
V8-JS:
//创建v8执行上下文
jsContext = Context::New();
//获得全局对象
Handle
//添加名字对象
AddObjectToSrcipt(global);
2.加载脚本
MS-JS:
//获取解析器
CComPtr
hr = m_pActiveScript->QueryInterface(IID_IActiveScriptParse, (void**)&srciptParser);
//初始化脚本解析器
hr = srciptParser->InitNew();
//解析脚本
hr = srciptParser->ParseScriptText(bstrScript, NULL, NULL,
NULL, 0, 0, SCRIPTTEXT_ISVISIBLE, NULL, NULL);
V8-JS:
//设置当前运行上下文
Context::Scope contextScope(jsContext);
//捕获异常
TryCatch tryCatch;
//编译脚本
Handle
Handle
Handle