本文來自衆成翻譯。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 的博客:關於流行
儘管讓 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 的博客:流行
JavaScript 的第一個公開發行版被集成到 1995 年發佈的 Netscape Navigator 2.0 中。多虧了虛擬化的奇蹟和過期軟件網站,咱們如今還能夠重現那些時刻!
不幸的是,那時不少 JavaScript 的基礎特性並不能用。匿名函數和原型鏈這兩個最強大的特性就遠遠沒有今天這麼完善。不過,這些特性已是該語言設計的一部分,會在後面幾年中正確實現。須要指出的是,在這個發行版中的 JavaScript 解釋器被認爲是處於 alpha 狀態。
幸運的是,一年後,1996 年發佈的 Netscape Navigator 3.0 已經有很大變化:
注意視頻中的錯誤是如何給咱們發生什麼事情的更多信息。這讓咱們推測解釋器以一種特殊的方式對待 prototype
屬性。因而咱們嘗試用基礎的 Object
實例來替換對象,這樣咱們以後就能夠修改該對象。嗯,好了,搞定了!至少在某種程度上。test
函數內的賦值貌似什麼都沒作。很顯然,還有不少工做須要去作。儘管如此,這個狀態的 JavaScript 對於不少任務是可用的,而且它已經開始流行了。
像正則表達式、JSON 和異常等特性此時依然不能用。在接下來的幾年中,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 標準是基於 Netscape Navigator 4 發佈的 JavaScript 版本,它依然缺失重要的特性,好比正則表達式、JSON、異常,以及內置對象的重要方法。不過,在瀏覽器中它工做得不錯。JavaScript 正開始變得愈來愈好。1997 年 6 月,版本 1 發佈了。
注意,視頻中那個簡單的原型和函數測試如今能夠正常工做了。在 Netscape 4 中不少工做已經在幕後完成了,而 JavaScript 從受益良多。如今咱們的示例基本上能夠與任何當代瀏覽器運行的同樣了。這對於 JavaScript 第一次發佈成一個標準來講,是一個很好的局面。
標準的第二版 ECMAScript 2 的發佈是用來糾正 ECMA 和 JavaScript ISO 標準(ISO/IEC 16262)之間的不一致性的,因此語言沒有作任何改動。這個版本發佈於 1998 年 6 月。
此版本的 JavaScript 的一個有趣的怪癖是,在編譯時沒有被捕獲的錯誤(這一般是留做爲未肯定的)交給解釋器任意決定如何處理。這是由於異常還不是該語言的一部分。
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,即異步 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 才能正確運行。
不幸的是,隨後幾年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 的將來。
此次會議的結論是:
與全部各方充分合做,集中精力完成 ES 3.1,到明年初肯定兩個執行標準。
下一步上的合做超出 ES3.1,會包含語法上的擴展,可是會在語義和語法創新上比 ES4 更謹慎。
有些 ES4 提案已經被認爲對 Web 不合理,最好不予討論:包、命名空間和早綁定。這個結論對於 Harmony 來講很關鍵。
ES4 的其它目標和理念正被改寫,以保持在委員會中的一致;包括類的概念是基於已有的 ES3 概念結合提議的 ES3.1 擴展。
總之,ECMAScript 4 花了近 8 年的時間開發,最後卻被廢棄了。這對涉及的全部人來講都是一個沉重的教訓。
單詞 "Harmony(和諧)" 出如今上面的結論中。這是未來對 JavaScript 擴展時項目的標準名稱。Harmony 會是全部人都贊成的方案。在 ECMAScript 3.1 發佈後(以版本 5 的形式,下面咱們會看到),全部 JavaScript 中要討論的新主意都會出如今ECMAScript Harmony 中。
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 }
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 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
方法(create
、defineProperty
、keys
、seal
、freeze
、getOwnPropertyNames
等等)
新的 Array
方法(isArray
、indexOf
、every
、 some
、map
、filter
、reduce
等等)
String.prototype.trim
和屬性訪問
新的 Date
方法(toISOString
、now
、toJSON
)
函數 bind
JSON
不可變的全局對象(undefined
、NaN
、Infinity
)
嚴格模式
其它次要的變動(parseInt
忽略前導零、拋出的函數有正確的 this
值,等等)
全部更新都不須要語法上的修改。那時 getter 和 setter 已經被不少瀏覽器非正式地支持。新的Object
方法經過給程序員更多工具來確保強制某些不變性,來改進「大型程序的編寫」(Object.seal
、Object.freeze
、Object.createProperty
)。嚴格模式經過阻止不少常見的錯誤源,在這一領域也成爲一種強大的工具。額外的 Array
方法改進了某些函數式範式(map
、reduce
、filter
、every
、some
)。另外一個大變化是 JSON:一個受 JavaScript 啓發的數據格式,如今經過 JSON.stringify
和 JSON.parse
原生支持了。其它變化基於實踐經驗在幾個方面做出了小的改進。總而言之,ECMAScript 5 是適度的改進,幫助 JavaScrpt 成爲一種對於小腳本和較大的項目來講都更可用的語言。依然有不少來自 ECMAScript 4 的好點子被廢棄,而且你會看到這些好點子又經過 ECMAScript Harmony 提案迴歸。
2011 年,ECMAScript 5 以 ECMAScript 5.1 的形式又來了一次迭代。這個版本澄清了標準中一些容易引發歧義之處,可是沒有提供任何新特性。全部的新特性定於在下一個 ECMAScript 的大發布中。
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 的將來是什麼呢?
也許目前進行中的最重要的第四階段提案是 async/await
。Async/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 }
把它與以下的 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,就應該讀讀這篇文章。自 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 上。