# 新时代新潮流WebOS 【17】需要不需要JavaScript

- 作者：邓侃
- 发布时间：2009-05-04 20:37
- 原文：https://www.ifanr.com/17760

Netscape于1994年成立，并迅速走红，1996年占据了浏览器 市场接近90%的市场份额。然而从1997年开始，在微软IE浏览器的强大攻势下，Netscape败走麦城，转眼到了2006年，Netscape的市 场份额只剩下1%不到。虽然Netscape昙花一现，但是短暂的辉煌，却留下了很多技术遗产，影响至今。

Brendan Eich 1986年毕业于UIUC，1995年入职Netscape，当时正值Netscape如日中天。入职后不久，Brendan Eich成功说服他的领导，开始了JavaScript的研究和开发，成为JavaScript之父。Brendan现在供职于Mozilla.com。

Brendan 在2008年8月23日的博客中写到，“我极其高兴地宣布，TraceMonkey正式投入使用。这是Firefox所使用的SpiderMonkey JavaScript engine的一次更新换代，TraceMonkey将植入在Firefox3.1版本，其亮点在于使用了一种新型的Just-In-Time（JIT） 编译器，使JavaScript的运行效率提高一个数量级以上。”

[![Benchmark comparison for JIT](https://s3.ifanr.com/wp-content/uploads/2010/08/BenchmarkcomparisonforJIT_thumb.png "Benchmark comparison for JIT")](https://s3.ifanr.com/wp-content/uploads/2010/08/BenchmarkcomparisonforJIT.png) *Figure 1. Benchmark comparison for JIT*

图一显示了没有配备JIT的Firefox 3.0的SpiderMonkey JavaScript engine，与配备了JIT的TraceMonkey JavaScript engine的运行速度的比较。JavaScript包含的功能很多，处理各个功能的速度快慢不一。譬如，JavaScript engine处理Image object的速度非常快，但是处理数学运算例如matrix，通常会慢很多。Brendan团队用四种不同的测试用例集（benchmarks），多方 面测试和比较，配备了JIT与没有配备JIT的两种JavaScript engines的运行效率。结论是配备了JIT，能使JavaScript engine的速度提高一倍甚至更多。

Brendan的博客隐含三个问题，1. 为什么JavaScript engine的运行速度很重要？2. 为什么JIT能够使JavaScript engine运行速度大大加快？3. 为什么选择JIT技术，而不是预先编译的办法？

第一个问题很好回答，因为JavaScript的应用领域日益广泛，譬如Google Docs，试图用Ajax技术实现基于浏览器的在线的Office软件，与离线的Microsoft的Word，PPT，Excel甚至Visio等等产 品竞争。但是Microsoft Office软件包含的运算逻辑非常复杂，譬如绘图软件Visio包含了大量的计算几何运算。虽然JavaScript应付简单的动态网页游刃有余，但是 面对这些大计算量的应用，JavaScript engine的运行速度就至关重要。

第二个问题，相对于逐句解析，JIT的优势在于可以 整段地编译源代码，而且缓存编译的结果，这样就避免了重复解析那些先前已经解析过了的源代码。另外整段编译并缓存编译结果，有利于优化代码，通常包括 inline expansion, dead code elimination, constant propagation, loop transformation, register allocation以及automatic parallelization等等。当然，优化代码是需要时间的，优化程度越高，运行时效率越高，但是启动时间越长。

第三个问题，为什么不用预先编译的办法。所谓预先编译，指的是开发者预先编译，在网站上发布编译好的二进制代码，而不是源代码。当浏览器访问到相关网页时，随即下载这些编 译好的二进制代码，然后直接运行之，省略掉了JIT编译的过程，也回避了逐句解析运行效率低下的弊端。为什么不预先编译JavaScript源代码？这个 问题表面上看起来也很容易回答，因为Java Applet曾经尝试过预先编译的办法，但是Java Applet以失败告终。这段历史教训似乎说明了，网页不应该绑定编译过的二进制代码，而最好只绑定文本形式的源代码。

但是如果深究一下Java Applet失败的原因，会发现不应该把Java Applet失败的罪责推卸给预先编译。

关于Java Applet失败的原因，Wikipedia谈到了兼容性的历史纠葛。Java的卖点是write once， run anywhere，所以Sun公司非常重视Java的兼容性。可是微软推出IE浏览器早期版本的时候，使用的Java虚拟机是微软自己的产品，其中包含一 些非标准的Java功能。这样，在IE浏览器中能够运行的Java Applet，不一定能够在其它浏览器中顺利运行。Sun找微软谈判，让微软去掉这些不合标准的Java功能，未果，于是对簿法庭。官司一打就是几年，控 辩双方精疲力竭。最后，微软宣布不再开发微软自己的Java虚拟机，同时IE浏览器也不预装Sun版的Java虚拟机。很多普通用户不知道如何自行安装 Java，当他们用浏览器访问网站时，如果遇到包含Java Applet的网页，就必须当场下载并安装JRE，这是一个非常耗时的过程，网页迟迟不能显示出来，导致用户体验很差。

假设历史上没有发生微软和Sun关于Java版本之争，Java Applet会不会大行其道呢？未必。

Wikipedia 还提到另一个Java Applet失败的原因，初看起来感觉有点吹毛求疵，但是反复想想，觉得其中大有深意。Wikipedia说，以Netscape为代表的一些浏览器，在 处理占满整个浏览器页面的Java Applets的时候，效果不佳，但是JavaScript勉强还行。让Java Applet脱离原先的浏览器页面，弹出一个新的窗口，也不是一个好办法。因为这样做，原先的浏览器页面就无所事事，用户会不自觉地关闭它，但是不曾想， 母体关闭了，Java Applet新窗口也随之关闭。

网页弹出一个窗口，是大家经常遇到的情况。为什么司空见惯的 小错误，对于Java Applet来说，却是不可容忍的大错呢？原因在于这样的做法，导致浏览器仅仅成为用户接触Java Applet的通道，一旦Java Applet的窗口打开了，浏览器本身就显得无足轻重。值得关注的观点是，用户接受并且喜爱浏览器的界面，他们不欢迎Java Applet把浏览器矮化成通道的做法，他们尤其不欢迎Java Applet的UI风格看起来和浏览器的风格不一致。

这个观点隐含的核心命题是，Java Applet之所以失败，根本原因在于Java Applet谋图游离于浏览器母体之外，寻求独立的倾向。

解释Java Applet为什么失败的猜想很多，如果这种观点仅仅是众多猜想之一，倒也无足轻重。但是继Java Applet之后，Sun进一步延续和深化让Java游离于浏览器母体之外的路线，推出了Java Web Start（JWS），JWS是否成功，可以验证这个猜想是否正确。

Java Applet是内置于浏览器框架中的插件，运行Java Applet的Java虚拟机是浏览器的一个内部组件。微软的IE浏览器，对于Sun的Java虚拟机，采取非暴力不合作的抵制态度。这个局面导致Sun 认定，欲大力推广Java Applet，必先绕开浏览器的制肘。在这种想法驱使下，Sun推出了Java Web Start（JWS）技术，以此替代先前的Java Applet。Java Web Start把浏览器彻底变成通道，一旦打开JWS，用户看到的不仅仅是弹出的另一个窗口，而且这个新窗口和浏览器母体没有紧密的联系。不仅JWS的UI渲 染完全可以用Java Swing实现，而且鼠标点击，敲键盘等等一系列事件的捕捉和响应，也完全由Java Swing控制，和浏览器无关。

与Java Applet的命运类似，JWS也没有大行其道。批评者认为，失败的根源在于JWS的设计理念有缺陷，

1\. JWS的UI渲染风格与浏览器不同，同时，JWS渲染UI的速度也比浏览器慢，原因是浏览器直接调用图形函数库，而不需要像Java那样，需要经过JVM的转手。

关于这一点，笔者多少有点疑虑，JVM的确会造成运行效率的降低，但是浏览器需要解析HTML和CSS，这个过程同样也会耗费时间。有没有 benchmarks，比较一下渲染相同的页面，JWS和浏览器各需要多长时间？但是话又说回来，即便JWS与浏览器在UI渲染的速度方面不相上下，也没 有充足的理由让JWS重复浏览器的工作，尤其是当浏览器已经做得足够好，并且已经被用户广泛接受。

2\. JWS游离于浏览器之外，把浏览器仅仅作为HTTP数据传输的通道，这样的做法隐含着IPC的overhead。原因是，浏览器和JWS运行在两个不同的 进程，浏览器与JWS之间的数据传输不可避免地依赖于Inter Process Communication (IPC），而IPC也影响运行效率。

详细说来，JWS和浏览器这两个进程之间交换数据，是通过message passing来实现的。在两个不同进程之间传递数据的过程，原理上很简单，sender进程把需要传输的数据，逐段复制并存入CPU的register 缓存空间，然后receiver进程从CPU的register读取数据。但是假如CPU正在处理其它工作，那么在执行IPC之前，首先要暂时中止当前的 工作，等待IPC结束后，再继续进行这份工作。在CPU中止当前的工作的时候，需要首先把CPU register空间里，当前正在处理的数据(switchframe)复制一份，缓存起来。当receiver读取完数据以后，再把缓存起来的数据 (switchframe)，重新移入CPU register。显而易见，把CPU register里的数据复制移出，然后再重新移入，是需要消耗资源的，这就是所谓不同进程之间的IPC，所引发的context switch的代价。

3\. 对于JWS的批评，并不是针对Java本身。相反，批评者们认为，Java和浏览器是天生班配的一对，应该取长补短，相得益彰，而不是试图取代对方。说得具体点，

a. 让浏览器专注于UI的渲染工作，以及鼠标点击和键盘输入等等事件的捕捉。

b. 让Java专注于数据逻辑的处理。

c. 系统架构方面，不应该以渲染机为中心，把Java作为插件。应该让Java承担起浏览器的整体控制工作，而渲染机作为浏览器的一个模块，负责UI绘制和事件捕捉。

d. 丰富Java对于HTML DOM object的处理功能，换而言之，所有今日JavaScript有关HTML DOM的APIs，Java都必须实现。

4\. Sun Microsystem不应该因为商务上的受挫，就愤然让Java背离浏览器。Java与浏览器，或者更准确地讲，Java与渲染机，合则两利，分则两伤。HotJava浏览器本来有远大前途，raner浅尝辄止，实在可惜。

[![Browser War I and II](https://s3.ifanr.com/wp-content/uploads/2010/08/BrowserWarIandII_thumb.png "Browser War I and II")](https://s3.ifanr.com/wp-content/uploads/2010/08/BrowserWarIandII.png) *Figure 2. Browser War I and II*

回到标题的话题，有一种观点认为，需要不需要JavaScript， 取决于有没有更好的替代品出现。JavaScript的原罪在于它是一个文本格式的脚本语言，对于文本格式的脚本语言，要么当场逐句解析，要么当场JIT 编译，无论如何，性能都不会超越预先编译。JavaScript的兴起，在于Java Applet的没落。Java Applet之所以没落，是因为没有与HTML-DOM紧密关联。JavaScript之所以成功，并不在于这个语言的内核有多少优势，而是在于它提供了 简洁方便的操控HTML-DOM的APIs。如果对于Java Applet加以改造，丰富其操控HTML-DOM的APIs，则Java Applet不一定没落，因之，JavaScript也未必会兴起。

从这个观点出发，浏览器需要重构。与第一代和第二代浏览器不同，新一代浏览器不再以WebKit之类渲染机为中心，而是以Java-DOM操控为中心，渲染机为专项功能。在新一代浏览器中，本质上不需要JavaScript的存在，除非需要反向兼容老旧的含有JS的网页。

所谓第一代和第二代浏览器，并没有严格划分。1989年，欧洲原子能研究组织（CERN）的一名合同工，牛津大学的毕业生Tim Berners-Lee，提出了用HTTP协议构筑万维网（World Wide Web）的设想。1993年，美国国立超级计算应用中心（NCSA）开发了Mosaic浏览器，并被广为接受，从而拉开了第一次浏览器大战的序幕。继承 Mosaic的衣钵而发展起来的Netscape浏览器，曾经辉煌一时，1996年占据了90%左右的市场份额。可惜好景不长，1995年微软决定开发 IE浏览器，到了1997年，IE的竞争势头已经锐不可挡，到了2003年，Netscape大势已去，第一次浏览器大战就此结束，以微软IE浏览器完胜 而告终。Mosaic，Netscape以及IE的6.0以前诸版本，还有史前的其它浏览器，通常被称为第一代浏览器。

自2003年以后，Mozilla Firefox，Apple Safari，Opera，以及2008年问世的Google Chrome，纷纷挑战微软IE，蚕食其市场份额。虽然从技术上讲，这些新兴的浏览器的确比IE有一些进步，但是技术上的局部优势，并没有大规模地吸引 IE的用户。

前面提到的观点，可以说是浏览器领域激进派的看法。他们认为，小修小补颠覆不了IE的霸主地位。根本的 解决办法，是重构浏览器，大幅度提高浏览器的性能，使之能够从容地处理更加复杂的计算逻辑，譬如Visio那样绘图功能，或者大计算量的网络游戏。只有这 样，才能争夺那些习惯于使用IE的用户。

笔者认为，PC上的浏览器，历史包袱沉重，要冲击现有浏览器的架构设计，估计困难重重。但是手机浏览器还处于诸侯混战之中，没有太多历史积淀。或许这是一个轻装上阵，试一试新一代浏览器的良好突破口。
