1.6 为JavaScript正名
到2005年,JavaScript就已经诞生十年了。然而十年之后,这门语言的发明者Brendan Eich还在向这个世界解释“JavaScript不是Java,也不是脚本化的Java(Java Scription)”。
这实在是计算机语言史上罕见的一件事了。因为如今几乎所有的Web页面中都同时包含了JavaScript与HTML,而后者从一开始就被人们接受,前者却用了十年都未能向开发人员说清楚“自己是什么”。
Brendan Eich在这份名为《JavaScript这十年》(JavaScript at Ten Years)的演讲稿中,重述了这门语言的早期发展历史:Brendan Eich自1995年4月受聘于网景公司,开始实现一种名为“魔卡(Mocha)”—JavaScript最早的开发代号或名称—的语言;仅两个月之后,为了迎合Netscape的Live战略而更名为LiveScript;到了1995年年末,又为了迎合市场对Java语言的热情,正式地、也是遗憾地更名为JavaScript,并随网景浏览器推出。
Brendan在这篇演讲稿最末一行写道:“不要让营销决定语言名称(Don't let Marketing name your language)”。一门被误会了十年的语言的名字之争,是不是就此结束了呢?
仍然不是。因为这十年来,JavaScript的名字已经越来越乱,更多市场的因素困扰着这门语言—好像“借用Java之名”已经成了扔不掉的黑锅。
1.6.1 JavaScript
我们先说正式的、标准的名词:JavaScript。它实际是指两项内容:
■ 一种语言的统称,该语言由Brendan Eich发明,最早用于Netscape浏览器。
■ 上述语言的一种规范化的实现。
在JavaScript 1.3之前,网景公司将它们在Netscape浏览器上的该语言规范的具体实现直接称为JavaScript,并一度以Client-Side JavaScript与Server-Side JavaScript区分该语言在浏览器NN(Netscape Navigator)与NWS(Netscape Web Server)上的实现—但后来它们改变了这个做法。而在JavaScript 1.3之后,我们在习惯上只采用上述的第二种说法:将所有这门语言的实现都称为JavaScript,而不再特指网景(以及后来的Mozilla)的。
然而在ECMAScript开始制定规范之后,这些实现又被统称为“基于ECMAScript标准的实现”,或者“ECMAScript的方言”。因此现在确切的说法是:
■ JavaScript是一种语言的统称,由ECMAScript-262规范来定义。
■ JavaScript包含了Core JavaScript、SpiderMonkey JavaScript、JScript等各种宣称自己实现了ECMAScript规范的引擎与语言(及其扩展),而非特指其一。
1.6.1.1 Core JavaScript
Core JavaScript这个名词早在1996年(或更早之前)就被定义过,但它直到1998年10月由网景公司发布JavaScript 1.3时才被正式提出来。准确地说,它是指由网景公司和后来的开源组织Mozilla,基于Brendan Eich最初版本的JavaScript引擎而发展出来的脚本引擎,是JavaScript规范的一个主要的实现者、继承者和发展者。
Core JavaScript的定义如图1-7所示。
图1-7 官方手册中有关Core JavaScript的概念说明
由于Netscape是早期网页浏览器的事实标准的制定者,因此那个时代的“Client-Side JavaScript”也就定义了所谓的“浏览器端JavaScript”的早期模型。这包括DOM、BOM模型等在内、沿用至今的对象体系和事件方法,并且也是目前JavaScript应用最为广泛的环境。
但到了JavaScript 1.3发布时,Netscape便意识到它们不能仅仅以Client/Server来区分JavaScript—因为市面上出现了多种JavaScript。于是它们做了一些小小的改变:在发布手册时,分别发布“Core JavaScript Guide”和“Client-Side JavaScript Guide”。前者是语言定义与语法规范,后者则是该语言的一种应用环境与应用方法。
所以事实上,对于Mozilla来说,自JavaScript 1.3版本开始,Core JavaScript 1.x与JavaScript 1.x是等义的。在这种语境下所说的JavaScript 1.x,就是指Core JavaScript,而并不包括Client-Side JavaScript。不过,由于一些历史原因,在Core JavaScript中会有一部分关于“LiveConnect技术”的叙述及规范。这在其他(所有的)JavaScript规范与实现中均是不具备的。
然而不幸的是,Apple公司有一个基于KJS实现的JavaScript引擎,名为JavaScriptCore,属于WebKit项目的一个组成部分—WebKit项目所实现的产品就是著名的开源跨平台浏览器Safari。所以在了解Core JavaScript的同时,还需强调它与JavaScriptCore的不同。
1.6.1.2 SpiderMonkey JavaScript
Brendan Eich编写的JavaScript引擎最后由Mozilla贡献给了开源界,SpiderMonkey便是这个产品开发中的开源项目的名称(code-name,项目代码名)。为了与通常讲述的JavaScript语言区分开来,我们使用SpiderMonkey来特指上述由Netscape实现的、Mozilla和开源社区维护的引擎及其规范。
Mozilla Firefox 4.0以后的版本对SpiderMonkey JavaScript进行了较大的更新,大量使用JIT(Just In Time)编译技术来提升引擎性能。并且从Firefox 4.0版本开始,Mozilla发布了JavaScript 1.8.5版本,开始支持ECMAScript规范下最新的语言特性。
在本书此后的描述中,凡称及SpiderMonkey JavaScript的,将是特指由Mozilla发布的这一引擎;凡称及JavaScript的,将是泛指JavaScript这一种语言的实现。
1.6.1.3 JScript
微软于1996年在IE中实现了一个与网景浏览器类似的脚本引擎,微软把它叫作JScript以示区别,结果JScript这个名字一直用到现在。Internet Explorer浏览器在那个时候几乎占尽市场,因此在1999年之后,Web页面上出现的脚本代码基本上都是基于JScript开发的,而Core JavaScript 1.x却变成了“(事实上的)被兼容者”。
直到2005年前后,源于W3C、ECMA对网页内容与脚本语言标准化的推动,以及Mozilla Firefox成功地返回浏览器市场,Web开发人员开始注重所编写的脚本代码是否基于JavaScript的标准—ECMAScript规范,这成为新一轮语言之争的起点。
现在的微软浏览器(Microsoft Edge)中已经启用了称为Chakra的新引擎,因此JScript只用于特指Internet Explorer系列的浏览器环境中内置的JavaScript引擎。不过,另外在Windows Script Host(WSH)、Active Server Page(ASP)等脚本开发环境中也包括JScript这一语言的实现,某些环境下它们也被称为ActiveScript。
1.6.2 ECMAScript
JavaScript的语言规范由网景公司提交给ECMA(European Computer Manufacturers Association,欧洲计算机制造协会)去审定,并在1997年6月发布了名为ECMAScript Edition 1的规范,或者称为ECMA-262。4个月后,微软在IE 4.0中发布了JScript 3.0,宣称成为第一个遵循ECMAScript规范实现的JavaScript脚本引擎。而因为计划改写整个浏览器引擎的缘故,网景公司整整晚了一年才推出“完全遵循ECMAScript规范”的JavaScript 1.3。
请注意到这样一个事实:网景公司首先开发了JavaScript并提交给ECMA进行标准化,但在市场的印象中,网景公司的Core JavaScript 1.3比微软的JScript 3.0“晚了一年”实现ECMA所定义的JavaScript规范。这直接导致了一个恶果:在ECMAScript Edition 3(ES3)发布的早期,JScript成为JavaScript语言的事实标准。这个局面一直到JScript 3.0以及SpiderMonkey JavaScript 1.5之后才明朗起来,如图1-8所示。
图1-8 JScript与JavaScript各版本之间的关系
由于两家主要的JavaScript早期实现者已经基于ES3达成了一致,因此随后的入局者—Google,在Chrome上实现的V8引擎也只得先遵循这一版本的规范。再后来,直到2015年,ECMA-262标准委员会终于发布了ECMAScript Edition 6,即ES6或ES2015,这才有了这门语言中第一个“标准早于引擎实现”的版本。
从本书的第3版开始,将完全基于ECMA-262规范的定义来讲述。但是出于本书讨论方法的需要,我并不严格以该规范的结构框架来介绍与分析语言特性。另外,对于部分特定的语言引擎,本书将列出不符合上述规范的实现,并有针对性地予以讨论。