JavaScript概述
1.1 Javascript簡史
在20世紀90年代,也就是早期的WEB站點上,所有的網頁內容都是靜態的,所謂靜態是指,除了點擊超鏈接,你無法通過任何方式同頁面進行交互,比如讓頁面元素接受事件,修改字體等。人們于是迫切的需要一種方式來打破這個局限,于是到了1996年,網景(Netscape)公司開始研發一種新的語言Mocha,并將其嵌入到自己的瀏覽器Netscape中,這種語言可以通過操縱DOM(Document Object Model,文檔對象模型)來修改頁面,并加入了對鼠標事件的支持。Mocha使用了C的語法,但是設計思想上主要從函數式語言Scheme那里取得了靈感。當Netscape 2發布的時候,Mocha被改名為LiveScript,當時可能是想讓LiveScript為WEB頁面注入更多的活力。后來,考慮到這個腳本語言的推廣,網景采取了一種宣傳策略,將LiveScript更名為JavaScript,目的是為了跟當時非常流行的面向對象語言Java發生曖昧的關系。這種策略顯然頗具成效,以至于到現在很多初學者還會為JavaScript和Java的關系而感到困惑。
Javascript取得成功了之后,確實為頁面注入了活力,微軟也緊接著開發自己的瀏覽器腳本語言,一個是基于BASIC語言的VBScript,另一個是跟Javascript非常類似的Jscript,但是由于Javascript已經深入人心,所以在隨后的版本中,微軟的IE幾乎是將Javascript作為一個標準來實現。當然,兩者仍然有不兼容的地方。1996年后期,網景向歐洲電腦廠商協會(ECMA)提交了Javascript的設計,以申請標準化,ECMA去掉了其中的一些實現,并提出了ECMAScript-262標準,并確定Javascript的正式名字為ECMAScript,但是JavaScript的名字已經深入人心,故本書中仍沿用Javascript這個名字。
1.1.1動態網頁
WEB頁面在剛開始的時候,是不能動態修改其內容的,要改變一個頁面的內容,需要先對網站上的靜態HTML文件進行修改,然后需要刷新瀏覽器。后來出現的JSP,ASP等服務器端語言可以為頁面提供動態的內容,但是如果沒有JavaScript則無法在服務器返回之后動態的在前端修改頁面,也無法有諸如鼠標移上某頁面元素則高亮該元素之類的效果,因此JavaScript的出現大大的豐富了頁面的表現,提高了用戶體驗。
而當AJAX流行起來之后,更多的非常絢麗的WEB應用涌現了,而且呈越來越多的趨勢,如Gmail,Google Map,Google Reader,Remember the milk,facebook等等優秀的WEB2.0應用,都大量的使用了JavaScript及其衍生的技術AJAX。
1.1.2瀏覽器之戰
1.1.3標準
1.2 JavaScript語言特性
JavaScript是一門動態的,弱類型,基于原型的腳本語言。在JavaScript中“一切皆對象”,在這一方面,它比其他的OO語言來的更為徹底,即使作為代碼本身載體的function,也是對象,數據與代碼的界限在JavaScript中已經相當模糊。雖然它被廣泛的應用在WEB客戶端,但是其應用范圍遠遠未局限于此。下面就這幾個特點分別介紹:
1.2.1動態性
動態性是指,在一個Javascript對象中,要為一個屬性賦值,我們不必事先創建一個字段,只需要在使用的時候做賦值操作即可,如下例:
- //定義一個對象
- var obj = new Object();
- //動態創建屬性name
- obj.name = "an object";
- //動態創建屬性sayHi
- obj.sayHi = function(){
- return "Hi";
- }
- obj.sayHi();
加入我們使用Java語言,代碼可能會是這樣:
- class Obj{
- String name;
- Function sayHi;
- public Obj(Sting name, Function sayHi){
- this.name = name;
- this.sayHi = sayHi;
- }
- }
- Obj obj = new Obj("an object", new Function());
動態性是非常有用的,這個我們在第三章會詳細講解。
1.2.2弱類型
與Java,C/C++不同,Javascript是弱類型的,它的數據類型無需在聲明時指定,解釋器會根據上下文對變量進行實例化,比如:
- //定義一個變量s,并賦值為字符串
- var s = "text";
- print(s);
- //賦值s為整型
- s = 12+5;
- print(s);
- //賦值s為浮點型
- s = 6.3;
- print(s);
- //賦值s為一個對象
- s = new Object();
- s.name = "object";
- print(s.name);
結果為:
text
17
6.3
Object
可見,Javascript的變量更像是一個容器,類似與Java語言中的頂層對象Object,它可以是任何類型,解釋器會根據上下文自動對其造型。
弱類型的好處在于,一個變量可以很大程度的進行復用,比如String類型的name字段,在被使用后,可以賦值為另一個Number型的對象,而無需重新創建一個新的變量。不過,弱類型也有其不利的一面,比如在開發面向對象的Javascript的時候,沒有類型的判斷將會是比較麻煩的問題,不過我們可以通過別的途徑來解決此問題。
1.2.3解釋與編譯
通常來說,Javascript是一門解釋型的語言,特別是在瀏覽器中的Javascript,所有的主流瀏覽器都將Javascript作為一個解釋型的腳本來進行解析,然而,這并非定則,在Java版的Javascript解釋器rhino中,腳本是可以被編譯為Java字節碼的。
解釋型的語言有一定的好處,即可以隨時修改代碼,無需編譯,刷新頁面即可重新解釋,可以實時看到程序的結果,但是由于每一次都需要解釋,程序的開銷較大;而編譯型的語言則僅需要編譯一次,每次都運行編譯過的代碼即可,但是又喪失了動態性。
我們將在第九章和第十章對兩種方式進行更深入的討論。
1.3 Javascript應用范圍
當Javascript第一次出現的時候,是為了給頁面帶來更多的動態,使得用戶可以與頁面進行交互為目的的,雖然Javascript在WEB客戶端取得了很大的成功,但是ECMA標準并沒有局限其應用范圍。事實上,現在的Javascript大多運行與客戶端,但是仍有部分運行于服務器端,如Servlet,ASP等,當然,Javascript作為一個獨立的語言,同樣可以運行在其他的應用程序中,比如Java版的JavaScript引擎Rhino,C語言版的SpiderMonkey等,使用這些引擎,可以將JavaScript應用在任何應用之中。
1.3.1客戶端Javascript
客戶端的JavaScript隨著AJAX技術的復興,越來越凸顯了Javascript的特點,也有越來越多的開發人員開始進行JavaScript的學習,使用Javascript,你可以使你的WEB頁面更加生動,通過AJAX,無刷新的更新頁面內容,可以大大的提高用戶體驗,隨著大量的JavaScript包如jQuery, ExtJS,Mootools等的涌現,越來越多的絢麗,高體驗的WEB應用被開發出來,這些都離不來幕后的JavaScript的支持。

圖JavaScript實現的一個WEB幻燈片
瀏覽器中的JavaScript引擎也進行了長足的發展,比如FireFox 3,當時一個宣傳的重點就是速度比IE要快,這個速度一方面體現在頁面渲染上,另一方面則體現在JavaScript引擎上,而Google的Chrome的JavaScript引擎V8更是將速度發展到了極致。很難想象,如果沒有JavaScript,如今的大量的網站和WEB應用會成為什么樣子。
我們可以看幾個例子,來說明客戶端的JavaScript的應用程度:

圖 ExtJS實現的一個網絡相冊,ExtJS是一個非常優秀的JavaScriipt庫

圖 ExtJS實現的一個表格,具有排序,編輯等功能
當然,客戶端的JavaScript各有側重,jQuery以功能見長,通過選擇器,可以完成80%的頁面開發工作,并且提供強大的插件機制,下圖為jQuery的UI插件:

總之,隨著Ajax的復興,客戶端的JavaScript得到了很大的發展,網絡上流行著大量的優秀的JavaScript庫,現在有一個感性的認識即可,我們在后邊的章節會擇其尤要者進行詳細講解。
1.3.2服務端Javascript
相對客戶端而言,服務器端的JavaScript相對平淡很多,但是隨著JavaScript被更多人重視,JavaScript在服務器端也開始迅速的發展起來,Helma, Apache Sling等等。在服務器端的JavaScript比客戶端少了許多限制,如本地文件的訪問,網絡,數據庫等。
一個比較有意思的服務端JavaScript的例子是Aptana的Jaxer,Jaxer是一個服務器端的Ajax框架,我們可以看這樣一個例子(例子來源于jQuery的設計與實現這John Resig):
- <html>
- <head>
- <script src="http://code.jquery.com/jquery.js" runat="both"></script>
- <script>
- jQuery(function($){
- $("form").submit(function(){
- save( $("textarea").val() );
- return false;
- });
- });
- </script>
- <script runat="server">
- function save( text ){
- Jaxer.File.write("tmp.txt", text);
- }
- save.proxy = true;
- function load(){
- $("textarea").val(
- Jaxer.File.exists("tmp.txt") ? Jaxer.File.read("tmp.txt") : "");
- }
- </script>
- </head>
- <body onserverload="load()">
- <form action="" method="post">
- <textarea></textarea>
- <input type="submit"/>
- </form>
- </body>
- </html>
runat屬性說明腳本運行在客戶端還是服務器端,client表示運行在客戶端,server表示運行在服務器端,而both表示可以運行在客戶端和服務器端,這個腳本可以訪問文件,并將文件加載到一個textarea的DOM元素中,還可以將textarea的內容通過Form表單提交給服務器并保存。
再來看另一個例子,通過Jaxer對數據庫進行訪問:
- <script runat="server">
- var rs = Jaxer.DB.execute("SELECT * FROM table");
- var field = rs.rows[0].field;
- </script>
var rs = Jaxer.DB.execute("SELECT * FROM table");
var field = rs.rows[0].field;
通過動態,靈活的語法,再加上對原生的資源(如數據庫,文件,網絡等)操作的支持,服務器端的JavaScript應用將會越來越廣泛。
當Google的JavaScript引擎V8出現以后,有很多基于V8引擎的應用也出現了,其中最著名,最有前景的當算Node.js了,下面我們來看一下Node.js的例子:
- <strong>var sys = require('sys'),
- http = require('http');
- http.createServer(function (req, res) {
- setTimeout(function () {
- res.sendHeader(200, {'Content-Type': 'text/plain'});
- res.sendBody('Hello World');
- res.finish();
- }, 2000);
- }).listen(8000);
- sys.puts('Server running at http://127.0.0.1:8000/');</strong>
保存這個腳本為sayHello.js,然后運行:
node sayHello.js
程序將會在控制臺上打印:
Server running at http://127.0.0.1:8000/
訪問http://127.0.0.1:8000,兩秒鐘之后頁面會響應:Hello, World。
再來看另一個官方提供的例子:
- <strong>var tcp = require('tcp');
- var server = tcp.createServer(function (socket) {
- socket.setEncoding("utf8");
- socket.addListener("connect", function () {
- socket.send("hello\r\n");
- });
- socket.addListener("receive", function (data) {
- socket.send(data);
- });
- socket.addListener("eof", function () {
- socket.send("goodbye\r\n");
- socket.close();
- });
- });
- server.listen(7000, "localhost");</strong>
訪問localhost的7000端口,將建立一個TCP連接,編碼方式為utf-8,當客戶端連接到來時,程序在控制臺上打印
hello
當接收到新的數據時,會將接收到的數據原樣返回給客戶端,如果客戶端斷開連接,則向控制臺打?。?/p>
goodbay
Node提供了豐富的API來簡化服務器端的網絡編程,由于Node是基于一個JavaScript引擎的,因此天生的就具有動態性和可擴展性,因此在開發網絡程序上,確實是一個不錯的選擇。
1.3.3其他應用中的Javascript
通過使用JavaScript的引擎的獨立實現,比如Rhino,SpliderMonkey,V8等,可以將JavaScript應用到幾乎所有的領域,比如應用程序的插件機制,高級的配置文件分析,用戶可定制功能的應用,以及一些類似與瀏覽器場景的比如Mozilla的ThunderBrid,Mozilla的UI框架XUL,筆者開發的一個Todo管理器sTodo(在第十章詳細討論)等。

圖 sTodo 一個使用JavaScript來提供插件機制的Java桌面應用
Java版的JavaScript引擎原生的可以通過使用Java對象,那樣將會大大提高JavaScript的應用范圍,如數據庫操作,服務器內部數據處理等。當然,JavaScript這種動態語言,在UI方面的應用最為廣泛。
著名的Adobe reader也支持JavaScript擴展,并提供JavaScript的API來訪問PDF文檔內容,可以通過JavaScript來定制Adobe Reader的界面以及功能等。
- app.addMenuItem({
- cName: "-",
- // menu divider
- cParent: "View",
- // append to the View menu
- cExec: "void(0);"
- });
- app.addMenuItem({
- cName: "Bookmark This Page &5",
- cParent: "View",
- cExec: "AddBookmark();",
- cEnable: "event.rc= (event.target != null);"
- });
- app.addMenuItem({
- cName: "Go To Bookmark &6",
- cParent: "View",
- cExec: "ShowBookmarks();",
- cEnable: "event.rc= (event.target != null);"
- });
- app.addMenuItem({
- cName: "Remove a Bookmark",
- cParent: "View",
- cExec: "DropBookmark();",
- cEnable: "event.rc= (event.target != null);"
- });
- app.addMenuItem({
- cName: "Clear Bookmarks",
- cParent: "View",
- cExec: "ClearBookmarks();",
- cEnable: "event.rc= true;"
- });
為Adobe Reader 添加了4個菜單項,如圖:

另一個比較有意思的JavaScript實例為一個在線的遺傳算法的演示,給定一個圖片,然后將一些多邊形(各種顏色)拼成一個圖片,拼圖的規則為使用遺傳算法,使得這些多變形組成的圖片與目標圖片最為相似:

可見,JavaScript在其他方面的也得到了廣泛的應用。
原文:http://abruzzi.iteye.com/blog/630410
【編輯推薦】