【转】JavaScript 简史

本文来自众成翻译。JavaScript 毋庸置疑是当今最重要的语言之一。Web 的兴起已经把 JavaScript 带到一个史无前例的地步。下面咱们来看看 JavaScript 在其短短历史中是如何演变的,以及它在走向何处。请继续读下去!javascript


这一切都开始于九十年代

一切都发生在 1995 年 5 月到 11 月这六个月内。网景通信公司在早期的 Web 中拥有强大的地位。它的浏览器 Netscape Communicator,做为第一款流行 Web 浏览器 NCSA Mosaic 的竞争对手,正得到普遍认同。网景是由 90 年代早期参与 Mosaic 开发的同一伙人创立的,而如今,有了钱和自主性,他们就有了寻求进一步扩展 Web 的途径所需的自由。而这种自由催生了 JavaScript。php

网景通信的创始人及前 Mosaic 团队的成员 Marc Andreessen 预见到 Web 须要某种方法变得更动态。动画、交互和其它形式的小动画应该是将来 Web 的一份子。因此 Web 须要一种能与 DOM 交互(不是跟你如今看到的这样一成不变)的小脚本语言。不过,这种脚本语言不该该面向大佬开发者,以及在软件工程方面有经验的人们——在当时这是一种重要的战略呼声。当时 Java 也在兴起,而且 Java applets 很快就要成为现实。因此这个用于 Web 的脚本语言须要迎合另外一群受众:设计师。实际上,那时 Web 是静态的。HTML 依然年轻,而且足够简单,非程序员也很容易学得会。因此,要让 Web 变得更动态,无论是浏览器的哪一部分,都应该让非程序员容易理解。这样 Mocha 的想法就诞生了。Mocha 要成为用于 Web 的一种脚本语言,它必须是简单、动态的,而且让非程序员容易理解。html

此时,JavaScript 之父 Brendan Eich走上了历史舞台。网景通信公司雇佣 Eich,是让他开发一种 “用于浏览器的 Scheme”。Scheme 是一种 Lisp 的方言,语法很简单,它动态而强大,而且本质上是函数式的。而 Web 须要相似这样的语言:语法容易掌握;动态的,以减小代码,加快开发;而且强大。Eich 看到有机会能够从事本身喜欢的事情,因而就入伙了。java

当时,迫于压力,必须尽快赶出一个工做原型。当时原名为 Oak 的 Java 语言正开始推进。Sun Microsystems 正大力推动 Java,网景通信公司即将与他们达成一项协议,让 Java 能够用在浏览器上。那么为何要开发 Mocha(JavaScript 早期的名字)呢?为何已经有了 Java,却还要开发一个全新的语言呢?当时的想法是,Java 不适合 Mocha 的目标受众:测试脚本编写人员、业余爱好者、设计师。对于用在浏览器这个角色上来讲,Java 确实太大过重了。因此当时他们的想法是让 Java 用于大型专业级组件开发;而 Mocha 将用于小型脚本任务。也就是说,Mocha 命中注定就是 Java 的脚本同伴,在某种程度上相似于 Windows 平台上 C/C++ 和 Visual Basic 之间的关系。git

与此同时,网景的工程师开始详细地研究 Java。他们甚至开始开发本身的 Java 虚拟机。不过,这个虚拟机很快被否决,由于它历来就没有实现与 Sun 的虚拟机的完美一致。程序员

此时有不少来自于内部的压力,要尽量快地选择一门语言。Python、Tcl 以及 Scheme 自己都是可能的候选。因此,Eich 必须快搞。不过,他比别人有两个优点:能够自由挑选适合的特性集、能够直达拍板的人。不幸的是,他也有一个大的劣势:没有时间。必需要作出不少重要的决定,而作出决定的可用时间又很短。JavaScript,即 Mocha,就是在这种背景下诞生的。几周以内,一个工做原型就推出了,而后就被集成到 Netscape Communicator 中。es6

因而,本应是用于浏览器的 Scheme,如今就截然不同了。与 Sun 达成协议的压力,以及让 Mocha 变成 Java 的脚本同伴,束缚住了 Eich 的手脚。新语言须要采用相似 Java 的语法,对于不少经常使用语还采用了熟悉的语义。因此 Mocha 一点也不像 Scheme。它表面上看像是一种动态的 Java,实际上倒是Scheme 和 Self 的早产私生子,但长的像 Java。github

1995 年 5 月, Mocha 的原型被集成到 Netscape Communicator 中。很快,它被重命名为 LiveScript。当时,"live" 这个单词只是为了营销方便。1995 年 12 月,网景通信公司和 Sun 达成协议:Mocha/LiveScript 将被从新命名为 JavaScript,它将会做为浏览器中小型客户端任务的一种脚本语言,同时 Java 将会被提高为一种更大的、开发富 Web 组件的专业工具。web

初版的 JavaScript 敲定了该语言中不少如今知名的特性,特别是其对象模型以及函数式特性在此版本中已经出现了。ajax

若是当时 Eich 未能按时赶出一个工做原型,很难说会发生什么。其余可选方案一点也不像 Java。Python、Tcl 和 Scheme 都与 Java 大不相同。对于 Sun 公司来讲,很难接受一个与 Java 如此不一样的同伴语言,或者在历史和开发上比 Java 自己早的语言。另外一方面,Java 很长一段时间是 Web 的一个重要部分。若是 Sun 从没有过这样的地位,网景可能会在挑选这样一个语言上有更多的自由。这是确定的。不过,若是就算网景本身内部能控制和开发,它会不会选择采用外部的解决方案呢?咱们将永远不会知道。

不一样的实现

当 Sun 和 Netscape 达成协议,将 Mocha/LiveScript 的名称改成 JavaScript 时,有个大问题被提出来了:其余实现会怎么办?实际上,尽管 Netscape 很快成为了当时首选的浏览器,不过微软也正在开发 Internet Explorer。从最开始,JavaScript 就带来了用户体验如此大的差别,竞争浏览器没办法,只能本身也整一套 JavaScript 的实现。此时(而且很长一段时间),Web 标准还不强大。因此微软实现了本身版本的 JavaScript,叫作 JScript。从名称中去掉 “Java”,是为了不潜在的商标问题。不过,JScript 不只仅是名称上的不一样。它在实现上也略有不一样,特别是与某些 DOM 函数有关的实现上有所不一样,由此产生的影响一直波及到多年以后的将来。JavaScript 大战还发生除了名称和时间表以外的更多方面上,而它的怪癖正是这些大战打来的创伤。JScript 的第一个版本包含在 1996 年 8 月发布的 IE 3.0 中。

网景的 JavaScript 实现也采用了一个内部名称。和 Netscape Navigator 2.0 一块儿发布的版本被称为 Mocha。在 1996 年秋天,Eich 为了偿还匆忙推出它所欠下的技术债,将 Mocha 的大部分重写为一个更干净的实现。这个新版本的网景 JavaScript 引擎叫作 SpiderMonkey。SpiderMonkey 如今依然是 Netscape Navigator 的孙子 Firefox 中 JavaScript 引擎的名称。

有好几年,JScript 和 SpiderMonkey 是主要的 JavaScript 引擎。两者共同实现的功能(并不是老是兼容)会定义接下来几年中 Web 的样子。

主要设计特色

尽管 JavaScript 是仓促之做,不过有几个强大的特性在一开始就具有了。这些特性将 JavaScript 定义为一门语言,尽管有各类怪癖,依然让它能独树一帜。

是使用一门已有的语言,仍是发明一门新的语言,这也不是我能决定的。来自高层工程管理人员的强制命令是这门语言必须“看起来像 Java ”。这实际上也就把 Perl、Python、 Tcl 以及 Scheme 这些已有的语言排除掉了。后来,在 1996 年,John Ousterhout 在给 Tk 作宣传时还感叹说,Tcl 错过了这样一个很好的机会。我并不是骄傲,只不过是很高兴我选择 Scheme 式的一等函数以及 Self 式(尽管很怪异)的原型做为主干。至于 Java 的影响,主要是把数据分红基本类型和对象类型两种(好比字符串和 String 对象),以及引入了Y2K 日期问题,这真是不幸。 - Brendan Eich 的博客:关于流行

类 JAVA 的语法

尽管让 JavaScript 语法接近 Java 并不是初衷,不过市场力量让它变成了这样。退一步想,即便采用与 Java 不一样的语法可能会让实现某些特性更为方便,可是不能否认,采用熟悉的语法更有助于 JavaScript 的普及。

将以下的 Java 示例:

 1 public class Sample {
 2   public static void main(String[] args) {
 3     System.out.println("Hello world!");
 4     try {
 5       final MissileSilo silo = new MissileSilo("silo.weapons.mil");
 6       silo.launchMissile(args[0]);
 7     } catch(Exception e) {
 8       System.out.println("Unexpected exception: " + e);
 9     }
10   }
11 }

与以下(现代) JavaScript 示例作比较:

1 console.log('Hello world');
2 try {
3   const silo = new MissileSilo('silo.weapons.mil');
4   silo.launchMissile(process.argv[0]);
5 } catch(e) {
6   console.log('Unexpected exception' + e);
7 }

函数做为一等对象

在 JavaScript 中,函数只是又一个对象类型。它们能够像任何其它元素同样传递,能够被绑定到变量。在稍后版本的 JavaScript 中,函数甚至能够被抛出为异常。这个特性颇有多是在 JavaScript 开发时受到 Scheme 强烈影响的结果。

1 var myFunction = function() {
2   console.log('hello');
3 }
4 otherFunction(myFunction);
5 myFunction.property = '1';

经过让函数变成一等对象,某些函数式编程模式才成为可能。例如,较新版本的 JavaScript 利用了某些函数式模式:

1 var a = [1, 2, 3];
2 a.forEach(function(e) {
3   console.log(e);
4 });

这些模式已经被成功用于不少库,好比 underscore 和 immutable.js

基于原型的对象模型

尽管基于原型的对象模型是经过 JavaScript 得以流行的,不过它倒是在 Self 语言中首次引入。Eich 对这种模型有种强烈的偏好,它足够强大,可以模仿像 Java 或 C++ 这种基于 Simula 的语言中的更传统的方式。实际上,JavaScript 以后的版本中实现的类,也只不过是在原型系统之上的语法糖。

JavaScript 的原型灵感来自于 Self,而 Self 的设计目标之一就是要避免 Simula 风格的对象的问题。特别是,在 Simula 的方式下,类和实例之间的对立被看到是不少固有问题的诱因。有人认为,由于类为对象实例提供某种原型,随着代码演变和逐渐变大,就愈来愈难让这些基类适应不可预料的新需求。经过将实例做为新对象构建的原型,这种限制就被克服了。所以,原型的概念是:一个经过提供本身的行为,填补新实例的空白的实例。若是一个原型被认为不适合于一个新对象,那么它只须要被克隆和修改,而不会影响全部其它子实例。这在基于类的方式中是挺难作到的(即,修改基类)。

 1 function Vehicle(maxSpeed) {
 2     this.maxSpeed = maxSpeed;
 3 }
 4 
 5 Vehicle.prototype.maxSpeed = function() {
 6     return this.maxSpeed;
 7 }
 8 
 9 function Car(maxSpeed) {
10     Vehicle.call(this, maxSpeed);
11 }
12 
13 Car.prototype = new Vehicle();

原型的威力让 JavaScript 变得超级灵活,引起了不少带有本身对象模型的库的开发。一个流行的库 Stampit 就重度使用了原型系统,采用在基于类的传统方法下不可能的方式,来扩充和操做对象。

原型让 JavaScript 表面上看起来简单,可是给库的做者带来了自主权。

大怪癖:基础类型与对象

也许在匆忙开发的 JavaScript 中,最大的错误之一是某些行为相似的对象有不一样的类型。例如,字符串字面量("Hello world")的类型与 String 对象(new String('Hello world'))的类型就是不相同的。这就让咱们有时候不得不采用没必要要的、容易混淆的类型检查。

> typeof "hello world"
< "string"

> typeof new String('hello world')
< "object"

然而,在 JavaScript 历史中,这只是个开始。它的仓促开发真真切切地致使了一些设计失误。不过,发明一种用于动态 Web 的语言的优点不能耽搁,其它的一切只有交给历史了。

余下的是逆袭的、残酷的历史。JS 在客户端打败了 Java,竞争的只有 Flash,而 Flash 支持 JS 的后代 ActionScript - Brendan Eich 的博客:流行

追忆往事:看看 Netscape Navigator 2.0 和 3.0

JavaScript 的第一个公开发行版被集成到 1995 年发布的 Netscape Navigator 2.0 中。多亏了虚拟化的奇迹和过期软件网站,咱们如今还能够重现那些时刻!

不幸的是,那时不少 JavaScript 的基础特性并不能用。匿名函数和原型链这两个最强大的特性就远远没有今天这么完善。不过,这些特性已是该语言设计的一部分,会在后面几年中正确实现。须要指出的是,在这个发行版中的 JavaScript 解释器被认为是处于 alpha 状态。

Netscape Navigator 2

幸运的是,一年后,1996 年发布的 Netscape Navigator 3.0 已经有很大变化:

Netscape Navigator 3

注意视频中的错误是如何给咱们发生什么事情的更多信息。这让咱们推测解释器以一种特殊的方式对待 prototype 属性。因而咱们尝试用基础的 Object 实例来替换对象,这样咱们以后就能够修改该对象。嗯,好了,搞定了!至少在某种程度上。test 函数内的赋值貌似什么都没作。很显然,还有不少工做须要去作。尽管如此,这个状态的 JavaScript 对于不少任务是可用的,而且它已经开始流行了。

像正则表达式、JSON 和异常等特性此时依然不能用。在接下来的几年中,JavaScript 会迅猛发展。

ECMAScript: JavaScript 标准

JavaScript 公开发布后的第一次重大改变是以 ECMA 标准化的形式出现。ECMA 是 1961 年成立的一个行业协会,该协会只从事信息和通信系统的标准化。

JavaScipt 的标准化工做始于 1996 年 11 月。标准号是 ECMA-262,负责的委员会是 TC-39。这时候,JavaScript 已是不少页面的流行元素。这份1996 年的新闻稿 说采用 JavaScript 的页面数量已达 300,000。

JavaScript 和 Java 是开发 Internet 和 Intranet 应用程序的 Netscape ONE 平台的基础技术。自去年引入它们的很短一段时间内,新语言快速被开发者接受。根据 www.hotbot.com 统计,在当今互联网上有 175,000 个新 Java 小程序和超过 300,000 个使用 JavaScript 的页面。-Netscape 新闻稿

对于这样一个年轻的语言来讲,标准化是一个重要的步骤,不过依然是一个重大的号召。它将 JavaScript 开放给更普遍的受众,而且给其它潜在的实现者在语言进化上的发言权。它还充当了约束其它实现者的用途。那时候,人们担忧微软或者其它人会偏离默认的实现太远,从而致使分裂。

因为商标的缘由,ECMA 委员会不能用 JavaScript 作名字,而其它名称也有不少人不喜欢。因此通过几轮磋商后,决定这个用标准来描述的语言将被叫作 ECMAScript。如今,JavaScript 只是 ECMAScript 的商业名称。

ECMAScript 1 和 2:标准化之路

第一个 ECMAScript 标准是基于 Netscape Navigator 4 发布的 JavaScript 版本,它依然缺失重要的特性,好比正则表达式、JSON、异常,以及内置对象的重要方法。不过,在浏览器中它工做得不错。JavaScript 正开始变得愈来愈好。1997 年 6 月,版本 1 发布了。

Netscape Navigator 4

注意,视频中那个简单的原型和函数测试如今能够正常工做了。在 Netscape 4 中不少工做已经在幕后完成了,而 JavaScript 从受益良多。如今咱们的示例基本上能够与任何当代浏览器运行的同样了。这对于 JavaScript 第一次发布成一个标准来讲,是一个很好的局面。

标准的第二版 ECMAScript 2 的发布是用来纠正 ECMA 和 JavaScript ISO 标准(ISO/IEC 16262)之间的不一致性的,因此语言没有作任何改动。这个版本发布于 1998 年 6 月。

此版本的 JavaScript 的一个有趣的怪癖是,在编译时没有被捕获的错误(这一般是留做为未肯定的)交给解释器任意决定如何处理。这是由于异常还不是该语言的一部分。

ECMAScript 3:第一次大变更

ECMAScript 2 后工做在继续,对该语言的第一次大变动出现了。这个版本带来了:

  • 正则表达式

  • do-while 块

  • 异常和 try/catch 块

  • 更多有关字符串和数组的内置函数

  • 格式化数字输出

  • in 和 instanceof 运算符

  • 更好的错误处理

ECMAScript 3 发布于 1999年 12 月。

这个版本的 ECMAScript 流传甚广。它被当时的全部主流浏览器所支持,并且多年后一直支持。即便到了今天,有些转译器依然能够在产生输出时,以这个版本的 ECMAScript 为目标。这让 ECMAScript 3 成为了不少库的基准目标,即便后来版本的标准发布了也是如此。

即便 JavaScript 愈来愈流行,它依然主要是一种客户端语言。不过,它不少新特性让它离打破这种牢笼更近。

2000年 11 月,Netscape Navigator 6 发布。这个版本是对过去版本的重大修订,支持 ECMAScript 3。大约在一年半后,Firefox 发布。它是一个基于 Netscape Navigator 代码库的精简版浏览器,也支持 ECMAScript 3。这些浏览器与 IE 一块儿,继续推进 JavaScript 的成长。

AJAX 的诞生

AJAX,即异步 JavaScript 和 XML,是一种在 ECMAScript 3 年代诞生的技术。虽然它并不是标准的一部分,不过微软为其 IE5 浏览器实现了某些对 JavaScript 的扩展。其中之一就是XMLHttpRequest 功能(以 XMLHTTP ActiveX 控件的形式)。该功能容许浏览器执行对服务器的异步 HTTP 请求,从而容许页面被即时动态更新。虽然术语 AJAX 直到几年后才被创造出来,可是这种技术早就处处在用了。

术语 AJAX 是由 Adaptive Path 的联合创始人 Jesse James Garrett 在这篇标志性博客中创造出来的。

XMLHttpRequest 被证实是很是成功的,多年之后被集成到一个单独的标准中(做为 WHATWG 和 W3C 组织的一部分)。

由实现者给语言带来一些有趣的东西,而且在浏览器中实现,从而促进特性的发展,依然是 JavaScript 和相关的 Web 标准(好比 HTML 和 CSS)继续发展的方式。不过,那时不一样派系之间沟通极少,致使拖延和分裂。平心而论,有了任何感兴趣的派系提出建议的程序,今天的 JavaScript 开发显得更有组织。

玩玩 NETSCAPE NAVIGATOR 6 Netscape Navigator 6

这个版本支持异常,以前版本在试图访问 Google 时候遇到的主要缺陷。难以想象的是,即便在今天,试图在这个版本中访问 Google,也会一个看得见的工做页面。相比之下,若是试图用 Netscape Navigator 访问 Google,就会被缺少异常、不完整的渲染以及糟糕的布局弄的焦头烂额。Web 正在快速发展,即便在当时。

玩玩 INTERNET EXPLORER 5 IE5

IE5 也能渲染当前版本的 Google。不过,众所周知,在实现某些特性上面,IE 和其它浏览器之间有不少分歧。这些分歧祸害了 Web 不少年,也是长期以来 Web 开发者受挫之源,由于他们常常不得不为 IE 用户实现特例。

实际上,要在 IE5 和 IE6 中访问 XMLHttpRequest 对象,必需要借助于 ActiveX。其它浏览器将其实现为原生对象。

var xhr = new ActiveXObject("Microsoft.XMLHTTP"); 

毫无疑问,是 IE5 率先将 AJAX 理念变成现实。不过,直到 IE7,微软才开始遵循标准,并更贴近共识。有些老公司网站依然须要老版本的 IE 才能正确运行。

ECMAScript 3.1 和 4:斗争之年

不幸的是,随后几年JavaScript 发展并不顺利。从 ECMAScript 4 的工做一开始,委员会中就开始出现了强烈的分歧。有一群人认为 JavaScript 须要一些特性来成为一种更强大的语言,这样就能够用于大型应用程序开发。这群人提出了不少特性,这些特性涉及面广,变化大。另外一群人认为大型应用程序开发不是 JavaScript 适合的方向。因为缺少一致意见,加上新提出的某些特性的复杂性,将 ECMAScript 4 的发布变得遥遥无期。

实际上针对 ECMAScript 4 的工做在 1999 年 版本 3 刚出炉的时候,就已经开始了。网景公司内部讨论了不少有意义的特性。不过,实现这些特性的兴趣已经逐渐减弱,而且 2003 年刚过没多久,在新版本 ECMAScript 上的工做就中止了。一个临时报告发布了,有些实现者,好比 Adobe(ActionScript)和微软(JScript.NET),使用这个报告做为其引擎的基础。2005 年,在 AJAX 和 XMLHttpRequest 的影响之下,再度激发了新版本 JavaScript 的兴趣,TC-39 重启了工做。几年过去了,特性集变得愈来愈大。在 ECMAScript 4 开发的最高峰,有以下这些特性:

  • 接口

  • 命名空间

  • 可选的类型注解

  • 可选的静态类型检查

  • 结构类型

  • 类型定义

  • 多方法(Multimethods)

  • 参数化类型

  • 尾调用

  • 迭代器(Iterator)

  • 生成器(Generator)

  • 内省

  • 类型识别的异常处理器

  • 常量绑定

  • 块做用域

  • 解构

  • 函数表达式

  • 数组推导式(Array comprehensions)

ECMAScript 4 草案将这个新版本描述为编写大型应用程序而设计。若是你已熟悉 ECMAScript 6/2015,就会注意到不少来自 ECMAScript 4 的特性被从新引入了。

虽然 ES3 灵活,而且在形式上很强大,可是在开发大型软件系统实践中,它的抽象能力常常是没法胜任的。因为在 Web 上采用 Ajax 编程,在应用程序中大量使用 ECMAScript 做为插件以及脚本语言,ECMAScript 程序正变得愈来愈大,愈来愈复杂。大型程序的开发能够从静态类型检查、名称隐藏、早绑定以及其它优化手段、直接支持面向对象编程等技术上大大受益,而这些都是 ES3 中所缺少的。 - ECMAScript 4 草案

一则有趣的历史片断是以下的 Google Docs spreadsheet,这个文件展现了几种 JavaScript 引擎的实现状态,以及涉及其中的派系的讨论。

开发 ECMAScript 4 的委员会由 Adobe、Mozilla、Opera(以非官方身份)和微软组成。Yahoo 在大部分标准和特性已经决定了后,进入了这个委员会。Doug Crockford,一个有影响力的 JavaScript 开发者,就是 Yahoo 为此送进委员会的那我的。他鼓吹他的担心,强烈反对不少 ECMAScript 4 提议的修改。他从微软的表明那里得到了强烈的支持。Crockford 本人说到:

可是结果微软的委员也有一样的担心 - 他也认为这门语言正变得太大,失去了控制。在我加入委员会以前,他什么都没有说,由于他担忧,若是微软试着阻拦这件事,就会被指责为反竞争行为。根据微软过去的表现,也许他们有一些不错的理由对此在乎 - 而且很显然,这些担心是有理有据的,由于已经发生过。可是我劝他说,微软应该作正确的事情,而且以他的声誉,他决定他应该,也能说服微软。因此微软就在 ES4 上改变了立场。 - Douglas Crockford — JavaScript 的现状和将来

开始是怀疑,后来就变成强势反对 JavaScript。微软拒绝接受 ECMAScript 4 的全部部分,而且准备采起各类必要的行动来阻止标准得到经过(甚至法律诉讼)。幸运的是,委员会中的人设法阻止了法律斗争。不过,缺少共识有效地阻止了 ECMAScript 4 推动。

微软的某些人想在这件事情上采起强硬手段,他们想开始创建书面凭据,开始走申诉程序,想作这些额外的法律程序。我可不想有这种事情。我是不一样意 ES4,可是仅限于技术层面,而且我想只限于技术层面;我不想让它变得比之前更麻烦。我只是想搞清楚什么事情该作,因此我设法温和一点。可是微软依然采起了极端立场,说他们拒绝接受 ES4 的任何部分。因此事情就变成了两极分化,可是我认为两极分化是由于 ES4 团队拒绝考虑任何其它观点的结果。那时委员会没有达成共识,这是件糟糕的事情,由于标准小组必需要达成共识。一个标准不该该是有争议的。 - Douglas Crockford — JavaScript 的现状和将来

Crockford 想出一个点子来推动,就是从新弄一个标准,这个标准更简单,减小一些特性集,这样全部人均可以赞成:没有新语法,只有来自使用该语言的经历中的实际提高。这个提案后来被称为 ECMAScript 3.1。

有一段时间,两种标准并存,而且设置了两个非正式的委员会。不过,ECMAScript 4 太复杂,没办法在面对冲突的状况完成。ECMAScript 3.1 更简单,而且尽管在 ECMA 中有斗争,它仍是完成了。

ECMAScript 4 的结束出如今 2008 年,Eich 经过一封电子邮件,发送了一次奥斯陆会议的内容提要,详细描述了 ECMAScrpt 走向和版本 3.1 和 4 的将来。

此次会议的结论是:

  1. 与全部各方充分合做,集中精力完成 ES 3.1,到明年初肯定两个执行标准。

  2. 下一步上的合做超出 ES3.1,会包含语法上的扩展,可是会在语义和语法创新上比 ES4 更谨慎。

  3. 有些 ES4 提案已经被认为对 Web 不合理,最好不予讨论:包、命名空间和早绑定。这个结论对于 Harmony 来讲很关键。

  4. ES4 的其它目标和理念正被改写,以保持在委员会中的一致;包括类的概念是基于已有的 ES3 概念结合提议的 ES3.1 扩展。

总之,ECMAScript 4 花了近 8 年的时间开发,最后却被废弃了。这对涉及的全部人来讲都是一个沉重的教训。

单词 "Harmony(和谐)" 出如今上面的结论中。这是未来对 JavaScript 扩展时项目的标准名称。Harmony 会是全部人都赞成的方案。在 ECMAScript 3.1 发布后(以版本 5 的形式,下面咱们会看到),全部 JavaScript 中要讨论的新主意都会出如今ECMAScript Harmony 中。

ActionScript

ActionScript 是一个基于 ECMAScript 4 早期草案的编程语言。Adobe 将其实现为 Flash 应用程序套件的一部分,也是它支持的惟一的脚本语言。这就让 Adobe 采用强硬的立场来支持 ECMAScript 4,甚至还将他们的引擎(Tamarin)开源发布了,以但愿加快 ECMAScript 4 的采纳。Adobe 员工 Mike Chambers 爆光了一个在此事上的有趣见解:

ActionScript 3 没有消失,咱们基于最近的决定,没有从中删除任何东西..咱们会继续跟踪 ECMAScript 规范,可是正如咱们一直所作的那样,咱们会创新,尽量推进 Web 向前发展(正如咱们在过去已作过的那样)- Mike Chamber 的博客

ActionScript 开发者指望 ActionScript 中的创新会驱动 ECMAScript 中的特性。不幸的是这事历来没有出现过,并且后来出如今 ECMAScript 2015 中的特性与 ActionScript 在不少方面不兼容。

有人看到这是微软尝试保持控制 ECMAScript 语言和实现的一种策略。此时,惟一可行的 ECMAScript 4 引擎是 Tamarin,因此此时占有 80% 浏览器市场份额的微软能够继续使用它本身的引擎(以及扩展),而不用承担切换到竞争对手的替代品的代价或者花时间内部实现一切。 其余人只是说微软的异议仅仅是技术上的,跟来自 Yahoo 的人同样。Microsoft 的引擎 JScript 此时与其它实现有不少差别。有人已经看到这是保持秘密控制该语言的一种手段。

ActionScript 目前依然是 Flash 的开发语言,而 Flash 随着 HTML5 的到来,逐渐淡出了人们的视野。

若是 ECMAScript 4 已经被流行 JavaScript 引擎实现的话,ActionScript 依然与它最像:

 1 package {
 2     import flash.display.Sprite;
 3     public class MyRectangle_v3 extends Sprite {
 4         private var _outlineWeight:Number;
 5         private var _color:uint;
 6         private var _xLocation:int;
 7         private var _yLocation:int;
 8         private var _rectangleWidth:int;
 9         private var _rectangleHeight:int;
10 
11         public function MyRectangle_v3(outlineWeight:Number, color:uint, 
12                                        xLocation:int, yLocation:int, 
13                                        rectangleWidth:int, rectangleHeight:int) {            
14             _outlineWeight = outlineWeight;
15             _color = color;
16             _xLocation = xLocation;
17             _yLocation = yLocation;
18             _rectangleWidth = rectangleWidth;
19             _rectangleHeight = rectangleHeight;
20         }  
21 
22         public function draw():void{
23             graphics.lineStyle(_outlineWeight);
24             graphics.beginFill(_color);
25             graphics.drawRect(_xLocation, _yLocation, _rectangleWidth, _rectangleHeight);
26             graphics.endFill();
27         }  
28     }  
29 }
View Code

E4X?什么是 E4X?

E4X 是一个公认的 ECMAScript 扩展的名称。它在 ECMAScript 4 开发期间发布(2004年),因此就采用了绰号 E4X。其实际名称是 ECMAScript for XML,并被标准化为 ECMA-357。E4X 扩充了 ECMAScript,以支持对 XML 内容的原生处理和解析。在 E4X 中,XML 被看成是一种原生数据类型。它最初被主流 JavaScript 引擎(好比 SpiderMonkey)采纳,不过以后因为不多有人用而被拿掉。在 Firefox 版本 21 中被删除。

除了其名称中有数字 "4" 以外,E4X 与 ECMAScript 4 没多大关系。

以下是一个使用 E4X 的示例:

 1 var sales = <sales vendor="John">
 2     <item type="peas" price="4" quantity="6"/>
 3     <item type="carrot" price="3" quantity="10"/>
 4     <item type="chips" price="5" quantity="3"/>
 5   </sales>;
 6 
 7 alert( sales.item.(@type == "carrot").@quantity );
 8 alert( sales.@vendor );
 9 for each( var price in sales..@price ) {
10   alert( price );
11 }
12 delete sales.item[0];
13 sales.item += <item type="oranges" price="4"/>;
14 sales.item.(@type == "oranges").@quantity = 4;

能够说,其它数据格式(好比 JSON)已经在 JavaScript 社区中得到了更普遍的认同,因此 E4X 出现和消失都没惹啥乱子。

ECMAScript 5:JavaScript 的重生

在 ECMAScript 4 的漫长斗争以后,从 2008 年开始,社区就在注意力放在 ECMAScript 3.1 上。ECMAScript 4 被废弃。在 2009 年,ECMAScript 3.1 完成,而且涉及的各方都签字确认了。而 ECMAScript 4 即便尚未真正发布,也已经被公认为是 ECMAScript 的一个特定变种,因此委员会决定将 ECMAScript 3.1 从新命名为 ECMAScript 5,以免混淆。

ECMAScript 5 成为了最受支持的 JavaScript 版本之一,也成为了不少转译器的编译目标。ECMAScript 5 被 Firefox 4 (2011)、Chrome 19 (2012)、Safari 6 (2012)、Opera 12.10 (2012) 和 Internet Explorer 10 (2012)彻底支持。

ECMAScript 5 是对 ECMAScript 3 的一种至关谨慎的更新,它包括:

  • Getter/setters

  • 数组和对象字面量中的尾随逗号

  • 保留关键字能够做为属性名

  • 新的 Object 方法(createdefinePropertykeyssealfreezegetOwnPropertyNames 等等)

  • 新的 Array 方法(isArrayindexOfevery、 somemapfilterreduce 等等)

  • String.prototype.trim 和属性访问

  • 新的 Date 方法(toISOStringnowtoJSON

  • 函数 bind

  • JSON

  • 不可变的全局对象(undefinedNaNInfinity

  • 严格模式

  • 其它次要的变动(parseInt 忽略前导零、抛出的函数有正确的 this 值,等等)

全部更新都不须要语法上的修改。那时 getter 和 setter 已经被不少浏览器非正式地支持。新的Object 方法经过给程序员更多工具来确保强制某些不变性,来改进“大型程序的编写”(Object.sealObject.freezeObject.createProperty)。严格模式经过阻止不少常见的错误源,在这一领域也成为一种强大的工具。额外的 Array 方法改进了某些函数式范式(mapreducefiltereverysome)。另外一个大变化是 JSON:一个受 JavaScript 启发的数据格式,如今经过 JSON.stringify 和 JSON.parse 原生支持了。其它变化基于实践经验在几个方面做出了小的改进。总而言之,ECMAScript 5 是适度的改进,帮助 JavaScrpt 成为一种对于小脚本和较大的项目来讲都更可用的语言。依然有不少来自 ECMAScript 4 的好点子被废弃,而且你会看到这些好点子又经过 ECMAScript Harmony 提案回归。

2011 年,ECMAScript 5 以 ECMAScript 5.1 的形式又来了一次迭代。这个版本澄清了标准中一些容易引发歧义之处,可是没有提供任何新特性。全部的新特性定于在下一个 ECMAScript 的大发布中。

ECMAScript 6 (2015) 和 7 (2016): 一个通用的语言

ECMAScript Harmony 提案成为未来对 JavaScript 的改进的中心。ECMAScript 4 的不少想法被永久封存了,但另一些则又以新的面目被从新启用。ECMAScript 6,后来被从新命名为 ECMAScript 2015,被指定为带来大变化。几乎全部须要在语法上改变的更新都被放到这个版本中。不过,此次委员会达成了一致,ECMAScript 6 最终于 2015 年发布。不少浏览器厂家已经开始着手实现它的特性,可是大的变更须要点时间。直到今天,并不是全部浏览器都彻底覆盖 ECMAScript 2015(虽然它们已经很接近)。

ECMAScript 2015 的发布致使转译器的使用大幅度增长,好比 Babel 或 Traceur。甚至在它发布以前,由于这些转译器跟踪了技术委员会的进展,人们已经体验了不少 ECMAScript 2015 的好处。

一些 ECMAScript 4 的大特性在这个版本的 ECMAScript 中被实现。不过,实现的出发点不同了。例如,ECMAScript 2015 中的类只不过是在原型之上的语法糖。这种思惟模式减轻了新特性的过渡和开发。

在咱们的JavaScript 2015 特性概述一文中,咱们对 ECMAScript 2015 的新特性作了一个全面的概述。你也能够看看 ECMAScript 兼容性表,了解一下在实现方面咱们如今的确切位置。

新特性小结以下:

  • Let(词法上的)和 const(不可从新绑定的)绑定

  • 箭头函数(匿名函数的简写)以及词法 this(包含做用域 this)

  • 类(原型之上的语法糖)

  • 对象字面量提高(计算键、短方法定义等等)

  • 模板字符串

  • Promise

  • Generator、iterable、iterator 和 for..of

  • 函数的默认参数及剩余运算符

  • 扩展语法

  • 解构

  • 模块语法

  • 新集合(Set、Map、WeakSet、WeakMap)

  • 代理和反射

  • Symbol 数据类型

  • 类型化数组

  • 内置支持子类化

  • 有保证的尾调用优化

  • 更简单的 Unicode 支持

  • 二进制和八进制字面量

类、let、const、promise、generator、iterators、模块,等等。这些特性都是为了把 JavaScript 带给更多受众,帮助开发大型应用程序。

你也许会惊讶,在 ECMAScript 4 失败之时,还有这么多特性能闯过标准化过程这一关。从这个层面上,必须得指出,ECMAScript 4 中不少最具侵入性的特性都没有被从新考虑,好比,命名空间、可选类型;同时,其它的特性被以能够经过以前的异议的方式从新考虑了,好比,让类成为原型之上的语法糖。ECMAScript 2015 依然是个苦差事,花了约 6 年完成(而且须要更长时间彻底实现)。不过,这样艰巨的一个任务能被 ECMAScript 技术委员会完成,也能够看做是个好兆头。

2016 年,一个 ECMAScript 的小修订版发布了。这个小修订版是 TC-39 实施的新发布过程的结果。全部新提案必须通过四个阶段的过程。每一个达到第四个阶段的提案有很大机会会被包含在下一个版本的 ECMAScript 中(不过委员会依然能够选择推迟将其列入议程)。这样,提案就几乎能够独立开发(不过与其它提案的交互必须在考虑之列)。提案不会中断 ECMAScript 的开发。若是一个提案已经准备列入,而且足够的提案已经达到第四阶段,那么就能够发布一个 ECMAScript 新版本。

2016 年发布的版本是一个至关小的版本。它包括:

  • 取幂运算符(**

  • Array.prototype.includes

  • 一些小的更正(generator 不能与 new 一块儿用等等)。

不过,在 2016 年,某些有趣的提案已经达到第四阶段,因此 ECMAScript 的将来是什么呢?

将来与超越:ECMAScipt 2017 及之后

也许目前进行中的最重要的第四阶段提案是 async/awaitAsync/await 是对 JavaScript 的一种语法扩展,可让处理 promise 变得更爽。例如,对于以下 ECMAScript 2015 代码:

 1 function apiDoSomethingMoreComplex(withThis) {
 2     const urlA = '...';
 3     const urlB = '...';
 4 
 5     httpLib.request(urlA, withThis).then(result => {
 6         const parsed = parseResult(result);
 7         return new Promise((resolve, reject) => {
 8             database.update(updateStatement, parsed).then(() => {
 9                 resolve(parsed);
10             }, error => {
11                 reject(error);
12             });
13         });
14     }).then(result => {
15         return httpLib.request(urlB, result);
16     }).then(result => {
17         return worker.processData(result);
18     }).then(result => {
19         logger.info(apiDoSomethingMoreComplex success (${result}));
20     }, error => {
21         logger.error(error);
22     });
23 }
View Code

把它与以下的 async/await 代码比较:

 1 async function apiDoSomethingMoreComplex(withThis) {
 2     const urlA = '...';
 3     const urlB = '...';
 4 
 5     try { 
 6         let result = await httpLib.request(urlA, withThis);
 7         const parsed = parseResult(result);
 8         await database.update(updateStatement, parsed);
 9         result = await httpLib.request(urlB, parsed);
10         result = await worker.processData(result);
11         logger.info(apiDoSomethingMoreComplex success (${result}));
12     } catch(e) {
13         logger.error(e);
14     }
15 }

其它第四阶段的提案在范围上都是次要的:

  • Object.values 和 Object.entries

  • 字符串补白

  • Object.getOwnPropertyDescriptors

  • 函数参数容许尾随逗号

这些提案都是定于在 2017 年发布,不过委员会可能会选择自行决定推迟。不过,仅是有async/await 这一点就是一件让人激动的变更。

可是将来并不是止步于此!咱们能够看看其它的一些提案,了解一下更远的将来会出现什么。一些有趣的提案是:

  • SIMD API

  • 异步迭代(async/await + 迭代)

  • Generator 箭头函数

  • 64 位 整型操做

  • Realm(状态分离/隔离)

  • 共享内存和原子

JavaScript 正愈来愈像一门通用的语言。不过,还有一件对 JavaScript 的将来会产生重大影响的大事情。

WebAssembly

若是你还没据说过 WebAssembly,就应该读读这篇文章。自 ECMAScript 5 发布以来,引起的库、框架和通常开发的激增,已经让 JavaScript 变成了对其它语言的一个有兴趣的目标。对于大的代码库,可互操做性是关键。好比说游戏。游戏开发的通用语言依然是 C++,而且它对不少架构来讲都是可移植的。将一个 Windows 游戏或者电子游戏移植到浏览器上被看做是一件不可能实现的任务。不过,当前 JIT JavaScript 虚拟机难以想象的性能让这成为可能。因而,像Emscripten 这种 LLVM-to-JavaScript 编译器应运而生。

Mozilla 看到了这点,并开始着手研究让 JavaScript 变成编译器的合适目标。Asm.js 诞生了。Asm.js 是 JavaScript 的一个严格子集,用来做为编译器的目标。JavaScript 虚拟机能够被优化为识别这个子集,而且生成比目前可能在普通 JavaScript 代码中更好的代码。浏览器慢慢变成了一个编译应用的全新目标,而 JavaScript 在其中心。

不过,有些限制是 Asm.js 也不能解决了。毕竟这与 JavaScript 的用途无关,因此必需要对 JavaScript 做出改变。要让 web 成为其它语言的合适目标,就须要点不一样的东西,而这正是 WebAssembly 全部的。WebAssembly 是用于 Web 的字节码。任何带有合适编译器的程序,均可以被编译为 WebAssembly,而后运行在合适的虚拟机上(JavaScript 虚拟机能够提供所需的语义)。实际上,首版 WebAssembly 就以与 Asm.js 规范一对一兼容为目标。WebAssembly 不只带来了加载时间更快的承诺(解析字节码比解析文本更快),还带来了 Asm.js 中目前还不能用的可能优化。想像一下,JavaScript 和你已有的代码之间能完美互用的 Web。

乍一看,这好像是危及到 JavaScript 的发展,然而事实刚好相反。经过让其它语言和框架更容易与 JavaScript 互用,JavaScript 就能够继续发展为一门通用的语言。而WebAssembly 是为此必需的工具。

目前,Chrome、Firefox 和 Microsot Edge 的开发版支持 WebAsembly 规范草案,而且可以运行演示应用程序

总结

JavaScript 的历史漫长而崎岖。它先被提议为用于 Web 的 Scheme,而后早早就被类 Java 的语法束缚住了。它的第一个原型在几周以内就被开发出来了。受市场之害,它在两年以内变了三个名字。而后被标准化了,同时获得一个听起来像皮肤病的名字。在三次成功的发布后,第四版陷入开发地狱约八年。开发方向一变再变,莫衷一是。而后,纯经过一个特性(AJAX)的成功,社区又重归行动一致,恢复了开发。第 4 版被废弃,一个次要版本,即人人皆知的 第 3.1 版本,被重命名为 第 5 版。第 6 版又在开发上花了不少年,不过此次委员会成功了,虽然又决定更名,可是此次是改成 2015。这个修订版很大,花了不少时间实现,可是最终,给 JavaScript 带来了新风。社区像之前同样活跃。Node.js、V8 和其它项目已经把 JavaScript 带到了一个史无前例的地步。Asm.js、WebAssembly 正进一步改进它。而且不一样阶段活跃的提案都让 JavaScript 的将来像之前同样光明。这是一条漫长的路,充满崎岖,而 JavaScript 依然始终是最成功的语言之一。这自己就是一种证实。永远把赌注押在 JavaScript 上。

相关文章
相关标签/搜索