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

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

圖 ExtJS實(shí)現(xiàn)的一個(gè)網(wǎng)絡(luò)相冊(cè),ExtJS是一個(gè)非常優(yōu)秀的JavaScriipt庫(kù)

圖 ExtJS實(shí)現(xiàn)的一個(gè)表格,具有排序,編輯等功能
當(dāng)然,客戶端的JavaScript各有側(cè)重,jQuery以功能見長(zhǎng),通過選擇器,可以完成80%的頁(yè)面開發(fā)工作,并且提供強(qiáng)大的插件機(jī)制,下圖為jQuery的UI插件:

總之,隨著Ajax的復(fù)興,客戶端的JavaScript得到了很大的發(fā)展,網(wǎng)絡(luò)上流行著大量的優(yōu)秀的JavaScript庫(kù),現(xiàn)在有一個(gè)感性的認(rèn)識(shí)即可,我們?cè)诤筮叺恼鹿?jié)會(huì)擇其尤要者進(jìn)行詳細(xì)講解。
1.3.2服務(wù)端Javascript
相對(duì)客戶端而言,服務(wù)器端的JavaScript相對(duì)平淡很多,但是隨著JavaScript被更多人重視,JavaScript在服務(wù)器端也開始迅速的發(fā)展起來,Helma, Apache Sling等等。在服務(wù)器端的JavaScript比客戶端少了許多限制,如本地文件的訪問,網(wǎng)絡(luò),數(shù)據(jù)庫(kù)等。
一個(gè)比較有意思的服務(wù)端JavaScript的例子是Aptana的Jaxer,Jaxer是一個(gè)服務(wù)器端的Ajax框架,我們可以看這樣一個(gè)例子(例子來源于jQuery的設(shè)計(jì)與實(shí)現(xiàn)這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屬性說明腳本運(yùn)行在客戶端還是服務(wù)器端,client表示運(yùn)行在客戶端,server表示運(yùn)行在服務(wù)器端,而both表示可以運(yùn)行在客戶端和服務(wù)器端,這個(gè)腳本可以訪問文件,并將文件加載到一個(gè)textarea的DOM元素中,還可以將textarea的內(nèi)容通過Form表單提交給服務(wù)器并保存。
再來看另一個(gè)例子,通過Jaxer對(duì)數(shù)據(jù)庫(kù)進(jìn)行訪問:
- <script runat="server">
- var rs = Jaxer.DB.execute("SELECT * FROM table");
- var field = rs.rows[0].field;
- </script>
通過動(dòng)態(tài),靈活的語法,再加上對(duì)原生的資源(如數(shù)據(jù)庫(kù),文件,網(wǎng)絡(luò)等)操作的支持,服務(wù)器端的JavaScript應(yīng)用將會(huì)越來越廣泛。
當(dāng)Google的JavaScript引擎V8出現(xiàn)以后,有很多基于V8引擎的應(yīng)用也出現(xiàn)了,其中最著名,最有前景的當(dāng)算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>
保存這個(gè)腳本為sayHello.js,然后運(yùn)行:
node sayHello.js
程序?qū)?huì)在控制臺(tái)上打印:
Server running at http://127.0.0.1:8000/
訪問http://127.0.0.1:8000,兩秒鐘之后頁(yè)面會(huì)響應(yīng):Hello, World。
再來看另一個(gè)官方提供的例子:
- <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端口,將建立一個(gè)TCP連接,編碼方式為utf-8,當(dāng)客戶端連接到來時(shí),程序在控制臺(tái)上打印
hello
當(dāng)接收到新的數(shù)據(jù)時(shí),會(huì)將接收到的數(shù)據(jù)原樣返回給客戶端,如果客戶端斷開連接,則向控制臺(tái)打?。?/p>
goodbay
Node提供了豐富的API來簡(jiǎn)化服務(wù)器端的網(wǎng)絡(luò)編程,由于Node是基于一個(gè)JavaScript引擎的,因此天生的就具有動(dòng)態(tài)性和可擴(kuò)展性,因此在開發(fā)網(wǎng)絡(luò)程序上,確實(shí)是一個(gè)不錯(cuò)的選擇。
1.3.3其他應(yīng)用中的Javascript
通過使用JavaScript的引擎的獨(dú)立實(shí)現(xiàn),比如Rhino,SpliderMonkey,V8等,可以將JavaScript應(yīng)用到幾乎所有的領(lǐng)域,比如應(yīng)用程序的插件機(jī)制,高級(jí)的配置文件分析,用戶可定制功能的應(yīng)用,以及一些類似與瀏覽器場(chǎng)景的比如Mozilla的ThunderBrid,Mozilla的UI框架XUL,筆者開發(fā)的一個(gè)Todo管理器sTodo(在第十章詳細(xì)討論)等。

圖 sTodo 一個(gè)使用JavaScript來提供插件機(jī)制的Java桌面應(yīng)用
Java版的JavaScript引擎原生的可以通過使用Java對(duì)象,那樣將會(huì)大大提高JavaScript的應(yīng)用范圍,如數(shù)據(jù)庫(kù)操作,服務(wù)器內(nèi)部數(shù)據(jù)處理等。當(dāng)然,JavaScript這種動(dòng)態(tài)語言,在UI方面的應(yīng)用最為廣泛。
著名的Adobe reader也支持JavaScript擴(kuò)展,并提供JavaScript的API來訪問PDF文檔內(nèi)容,可以通過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個(gè)菜單項(xiàng),如圖:

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

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