一、JavaScript發展歷程
1. 誕生
JavaScript因互聯網而生,緊跟瀏覽器的發展而發展。
1990年,歐洲核能研究所(CERN)科學家在互聯網(Internet)基礎上,發明了萬維網(World Wide Web),從此可以再網上瀏覽網頁文件。(互聯網是線路、協議以及通過TCP、IP協議實現數據電子傳輸的硬件和軟件的集合體。Internet提供的主要服務有萬維網WWW、文件傳輸FTP、電子郵件E-mail、遠程登錄Telnet等。萬維網則存在於互聯網之上,是由無數個網絡站點和網頁集合而成,構成了因特網主要的部分。如果把互聯網看成是基礎,萬維網就可以被看成是對互聯網的應用)
1992年,美國國家超級電腦應用中心(NCSA)開發了人類歷史上第一個瀏覽器Mosaic。
1994年,NCSA的程序員聯合一個風投家成立Mosaic通信公司,后來更名為Netscape。開發面向普通用戶的新一代瀏覽器Netscape Navigator1.0版,市場份額一舉超過90%。
Netscape公司很快發現,瀏覽器需要一種可以嵌入網頁的腳本語言來控制頁面行為。因為那時網速很慢而且網費很貴,有些操作不需要在服務端完成,可以把這些操作在瀏覽器端完成,從而提高效率。他們對這項腳本語言的設想是:功能不需要太強,語法簡單,容易學習和部署。
恰逢Sun公司java問世,兩家公司強強聯合,NetScript公司希望借助Java語言的聲勢,Sun公司則將自己的影響力擴展到瀏覽器,1995年,他們雇佣程序員十天時間就設計完成了這種語言的第一版,命名為JavaScript,對外宣稱JavaScript是Java的補充。
- 基本語法:借鑒C語言和Java語言
- 數據結構:借鑒Java語言,包括將值分為原始值和對象兩大類
- 函數用法:借鑒Schema語言和AWK語言,引入閉包
- 原型繼承模型:借鑒Self語言
- 正則表達式:借鑒Perl語言
- 字符串和數組處理:借鑒Python語言
2. JavaScript與Java的關系
JavaScript的基礎語法和對象體系,是模仿Java而設計的。
JavaScript語言的函數是一種獨立的數據類型以及基於原型對象的繼承鏈,是與java語法最大的兩點區別。
JavaScript不需要編譯,由解釋器直接執行。
3. JavaScript與ECMA的關系
1996年,微軟模仿JavaScript開發了一門相近的語言JScript,內置於IE3.0,Netscape公司面臨喪失瀏覽器腳本語言的主導權局面。胳膊拗不過大腿,Netscape又找了個大哥-國際標准化組織ECMA(European Computer Manufacture Association)來抵抗微軟。
1997年,ECMA組織發布262號標准文件(ECMA-262),里面規定了瀏覽器腳本語言的標准,並將這種語言成為ECMAScript。
4. JavaScript的版本
1997年,ECMAScript 1.0發布。
1998年,ECMAScript 2.0發布。
1999年,ECMAScript 3.0發布。
2007-2009年,ECMAScript 4.0草案發布,對3.0版本做了大幅升級,但是草案過於激進,各方發生嚴重分歧,中止4.0的開發,將其中涉及現有功能改善的一小部分,發布為ECMAScript 3.1,會后不久,改名為ECMAScript 5。
2011年,EMAScript 5.1發布,並成為ISO國際標准,到了2012年,所有主要瀏覽器都支持ECMAScript 5.1的全部功能。
2013-2015年,討論發布ECMAScript 6,並於2015年正式發布ECMAScript 6,更名為ECMASCript 2015。
5. 拓展-因特網標准制定(RFC)
- 因特網草案(Internet Draft)
- 建議標准,從這個階段開始就成為RFC文檔(Proposed Standard)
- 草案標准(Draft Standard)
- 因特網標准(Internet Standard)
二、JavaScript模塊化發展歷程
模塊化是指把一個復雜的系統分解到一個一個的模塊,優點有:
①代碼復用,更方便的進行代碼管理,同時方便於后面代碼的修改和維護
②一個單獨的文件就是一個單獨的模塊,一個單獨的作用域。只向外暴露特定的變量和函數,可以避免污染全局變量。
1. 無模塊化
Ajax出現之前,JS更多的用來在網頁上進行表單驗證,實現簡單的動畫效果。
2006年,ajax的概念被提出,前端擁有了主動向服務端發送請求並操作返回數據的能力,傳統的網頁慢慢向“富客戶端”發展。前端的業務邏輯越來越多,代碼也越來越多,於是一些問題就暴露出來:
- 全局變量的沖突
- 函數命名沖突
- 依賴關系不好管理
總結下要出場的“模塊化”這個概念需要解決哪些痛點:
- 如何安全的包裝一個模塊的代碼?不污染模塊外的任何代碼
- 如何唯一標示一個模塊?
- 如何優雅的把模塊的API暴露出去?不增加全局變量
- 如何方便的使用所依賴的模塊?
2. CommonJS
2009年,nodejs橫空出世,開創了一個新紀元,人們可以使用js來編寫服務端的代碼。
CommonJS模塊規范主要分為三部分:模塊引用(require)、模塊定義(export)、模塊標示(module)
- 模塊標示應遵循統一的規則
- 定義全局函數require,通過該標示來引入其他模塊,執行的結果即為其依賴模塊暴露出來的API,如果引入模塊中也包含相關依賴,則依次加載這些依賴,如果引入模塊失敗,則require函數應報一個異常
- 模塊通過變量export來定義自身同時向外界暴露自己,export只能是一個對象,暴露的API即為此對象的屬性
每個文件就是一個模塊,有自己的作用域。每個模塊內部,module變量代表當前模塊,是一個對象,它的exports屬性是對外的接口。module.exports屬性表示當前模塊對外輸出的接口,其它文件加載該模塊,實際上就是讀取module.exports變量。
require命令用戶加載模塊文件。
3. AMD
AMD(Asynchronous Module Definition)意思就是“異步模塊定義”。它采用異步方式加載模塊,模塊的加載不影響它后面語句的執行。所有依賴這個模塊的語句,都定義在一個回調函數中,等到加載完成之后,這個回調函數才會運行。
AMD也采用require語句加載模塊,但是不同於CommonJS,它要求兩個參數:
require([module],callback)
第一個參數[module],是一個數組,里面的成員就是要加載的模塊;第二個參數callback,則是加載成功之后的回調函數。
Layui中的JavaScript采用的便是AMD規范。
layui.use(['laydate', 'layer', 'table', 'upload', 'slider'], function(){
})
AMD是RequireJS的產出,可以異步加載JS文件,是一個依賴前置、異步定義的框架。
4. CMD
CMD(Common Module Definition)通用模塊定義,其提供了模塊定義和按需執行加載模塊。該規范明確了模塊的基本書寫格式和基本的交互規則。
CMD沒有依賴前置,通過require加載JQuery插件,依賴就近,在什么地方使用到插件就在什么地方require該插件,即用即返,這是一個同步的概念。
//CMD
define(function(require, exports, module) {
let a = require('./a');
a.doSomething();
···
let b = require('./b'); // 依賴可以就近書寫
b.doSomething();
...
})
// AMD 默認推薦的是
define(['./a', './b'], function(a, b) {
// 依賴必須一開始就寫好
a.doSomething()
...
b.doSomething()
...
})
5. ES6
CommonJS用於服務器,AMD用於瀏覽器,ES6在語言標准的層面上,實現了模塊功能,而且實現得相當簡單,完全可以取代CommonJS和AMD規范,成為瀏覽器和服務器通用的模塊解決方案。ES6模塊的設計思想是盡量的靜態化,使得編譯時就能確定模塊的依賴關系,以及輸入和輸出的變量。CommonJS和AMD模塊,都只能在運行時確定這些東西。
ES6模塊不是對象,而是通過export命令顯式指定輸出的代碼,再通過import命令輸入。
import { stat, exists, readFile} from 'fs';
上面代碼的實質是從fs模塊加載三個方法,其它方法不加載。這種加載稱為“編譯時加載”或者靜態加載,即ES6在編譯時就能完成模塊加載,效率比CommonJS模塊的加載方式高。
參考文章: