1.4 语言的进化

1.4.1Qomo的重生

这时的Qomo已经相当完整地实现了一门“高级语言”的大多数特性,我一时间便觉得Qomo失去了它应有的方向。原本作为产品的一个组成部分的WEUI是有着它的商业目的的,而Qomo v1.x~v2.0的整个过程中也有着“开源框架”这样的追求。但当这些目的渐渐远去的时候,Qomo作为一个没有商业和社区推动的项目,该如何发展呢?

我已经不止一次地关注到了Qomo核心部分的复杂性。在Qomo v2以前,这些复杂性由浏览器兼容、代码组织形式和语言实现技术三个方面构成。举例来说,考虑到Qomo的代码包可以自由地拼装,因此Interface层的实现就必须要能够完整地从整个框架中剥离出去;另外,Interface层又必须依赖于OOP层中所设计的对象实现框架。这使得Qomo v2不得不在Loader框架中加入了一种类似于编译器的“内联(Inline)”技术,也就是在打包的时候,将一些代码直接插入到指定的位置,以黏合跨层次之间的实现代码。

Inline带来的恶果之一,就是原本的Object.js被分成了9个片断——当使用不同的选项来打包的时候,这些片断被直接拼接到一个大的文件中;当使用动态加载方式装入Qomo的时候,则可以用“Inline”的方式在eval()代码文本的同时插入这些片断。

我意识到我在触碰一种新的技术的边界。这一技术的核心问题是:一个框架的组织原则与实现之间的矛盾。

Qomo到底应该设计为何种框架?是为应用而设计,还是仅仅围绕语言特性的扩展?在不同的选择之下,Qomo又应该被实现成什么样子?

在2007年末,我开启了一个新的项目,名为QoBean。

1.4.2 QoBean是对语言的重新组织

QoBean将问题直接聚焦于“语言实现”,开始讨论JavaScript语言自身特性的架构方式、扩展能力及新语言扩展的可能性。缘于这一设定,QoBean将Qomo中的语言层单独地拿了出来,并设定了一些基本原则:

█ 不讨论浏览器层面的问题。

█ 在ECMAScript规范的基础上实现,以保证可移植性。

█ 可以完全、透明地替换Qomo中的语言层。

█ 从语言原子做起。

“从语言原子做起”意味着它必须回归到对JavaScript语言的重新思考,即究竟什么才是JavaScript语言的“原子”。

“语言原子”这个词我最早读自李战的《悟透Delphi》。不过这本书终究没有出版,而李战兄后来写了一本《悟透JavaScript》,算是完成了他的悟透。至于引发我关于JavaScript原子问题的思考的,则是在本书第1版出版的前后,与起步软件的宋兴烈谈到JavaScript的一些特性,而他便提议将这些东西视做“原子特性”。

“这些东西”其实只有两个,其一是对象,其二是函数。它们初次在QoBean中的应用,便是“以极小的代价实现Qomo的整个类继承框架的完整体系”。而这一尝试的结果是:原本在Qomo中用了565行代码来实现的Object.js,在QoBean的描述中却只用了20行。进一步地,在新的QoBean中,为OOP语言层做的概念描述也只剩下了两行代码:

          MetaObject = Function;
          MetaClass = Function;

元语言的概念在Qomo/QoBean中渐渐浮现出来。2008年7月,亦即是在发布QoBean alpha1之后的半年,我为QoBean撰写了两篇博客文章:QoBean的元语言系统(一)、(二)。QoBean也在此时基本完成了对“Qomo的语言层”的重新组织。

事实上,QoBean本质上是探讨了JavaScript这门语言的一种扩展模式,即基于语言自身的原子特性进行二次实现的能力。这与后来的其他一些语言扩展,有着完全不同的路径,以及基本相同的目的。

我们在探索的是JavaScript这门语言的边界。

1.4.3 JavaScript作为一门语言的进化

JavaScript之父Brendan Eich曾说:“我们最初利用JavaScript的目的,是让客户端的应用不必从服务器重新加载页面即可回应用户的输入信息,并且提供一种功能强大的图形工具包给脚本编写者。”这包括在客户端的两个方面的功能,第一是用户交互,第二是用户界面。而展现与交互,正是现在对“前端职能”的两个主要定义。所以这个语言的最初构想,与它现在所应用的主要领域是悄然契合的。

但在新千年之后,浏览器取代传统的操作系统桌面渐渐成为热门的“客户端”解决方案,AJAX在这时作为一种客户端技术对这一技术选型起到了推波助澜的作用。与此同时,开发人员觉察到JavaScript作为一门语言,在客户端实现技术中难以有足够丰富的实现能力。于是语言级别的扩展纷纷出现:在代码组织上,开始有了命名空间;在运行效率上,有了编译压缩;在标准化方面,有了Common JS;在语言扩展上,有了在JavaScript中嵌入的解释语言……

对于传统的高级程序设计语言来讲,这一切是再自然不过了。然而JavaScript毕竟只是一种脚本语言,这些“附加的”扩展与“第三方的”实现事实上带来了更大的混乱。于是大公司开始提出种种“统一框架”,或者兼容并包的“整合方向”。在这一选择中,大公司首先解决的是“自己的”问题,这是由于在他们的种种产品、产品线中尤其需要这样一种统一的、标准的方案,以避免重复投入带来的开发与维护成本。因此,“商业化产品+自主的JavaScript开发包”成为一种时兴的产品模式。在这一产品模式中,由于JavaScript本身不具有源码保护的特性,因此源码开放既是战略,又是手段,也是不得已而为之的事。

现在我们有机会看到Plam手机平台上完整的Web OS的代码,也有机会直接读到FireBug中全部用于支持引擎级调试的代码,我们手边还有类似于YUI、Dojo等的企业级框架可用。然而,一切还是一如既往的乱。因为,这一切只是基于语言的扩展,而非语言或其基础库中的特性。造成这一事实的原因,既源于JavaScript自身初始设计的混合式特性,也因为ECMA(European Computer Manufacturing Association,欧洲计算机制造协会)在这门语言的标准化工作上的滞后与反复,如图1-6所示。

图1-6 JavaScript的语言特性发展及其标准化过程

JavaScript在发布v1.0的时候,仅有结构化语言的特性以及一些基础的面向对象特性(即Struct + Base OO),这一切直到v1.3的版本时才得以本质性的改观,使得这一语言成为包括动态语言、函数式语言特性在内的特性丰富的混合语言。这一切被ECMA通过标准化的形式确定下来,形成了以JavaScript 1.5和ECMAScript Ed3版本(即JS 1.5/ES3.1)为代表的,一直到我们今天仍在使用的JavaScript语言。

随后ECMA启动了一个工作组来进行下一代JavaScript的标准化工作,称为ECMAScript Ed4(亦即是ES4/JS2),这个小组的工作始于2003年3月。然而他们搞砸了整件事,他们几乎把JS2设计成了一门新的、大的、复杂的语言。因此,一方面一些需要“丰富的语言特性”的厂商不遗余力地推进着这一标准,另一方面它又被崇尚轻捷的前端开发人员诟病不已。迟至2009年年底,ECMA Ed4的标准化小组终于宣布:ES4的标准化暂停,并将基于ES4的后续工作称为ECMAScript Harmony。接下来,为了解决“互联网开发需要更新的、标准化的JavaScript语言”这一迫切问题,不久他们就发布了ECMAScript 5th这一版本,亦即是ES5。严格地说,ES5与ES4基本没有什么关系,而是对ES3.1所代表的语言方向的一个补充。

换言之,ES5没有改变JavaScript 1.x的语言特性;ES4则是一门集语言生产商所有创想之大成,而又与JavaScript 1.x倡导的语言风格相去甚远的语言。历史证明,我们暂弃了后者——过去10年,我们都未能将JavaScript 1.x推进到v2.0版本。

由于ES5秉承了JavaScript设计的原始思想,因此基于ES5又展开了新一轮的语言进化的角力(图1-6中的三条虚线试图说明,语言最初的特性设计是这一切的根源):

█ 第一个方向由Microsoft、Adobe等大厂商所倡导,沿着ES4——或称之为JS2、ECMAScript Harmony的方向,向更加丰富的面向对象(OO++)特性发展,主要试图解决大型系统开发中所需要的复杂的对象层次结构、类库及框架;

█ 第二个方向,则由包括Brendan Eich本人在内的语言开发者、研究者主导,他们力图增强JavaScript语言的函数式特性(Functional++),因为这样的语言特性在解决许多问题时来得比结构化的、面向对象的语言更优雅有效,而且从语言角度看来,函数式更为“纯粹”。

█ 在第三个方向上,Common JS等开发组意识到JS 1.x在应用于浏览器之外的开发场景中,以及在组织大型项目方面显得无力。而将这一问题归结起来,就是“缺乏基础运行框架和运行库”,于是通过参考传统的、大型的、系统级的应用开发语言,尝试性地提出在JavaScript中的同等解决方案(System++)。

具体的引擎或框架已经不再是被关注的话题。ES4的失败给整个JavaScript领域带来的思考是:我们究竟需要一种怎样的语言?