第一章:介紹 (fango)

fango發表於2012-06-20

個人電腦剛出現時,幾乎都帶著簡單的程式語言,通常是BASIC的一種。此語言與操作電腦緊密相連,因此每個電腦使用者,不管樂不樂意,都得嘗試。可現如今電腦氾濫,平常使用者卻只給個老鼠點點。這對絕大多數人已是很不錯了。但對我們這種有擺弄技術傾向者,日常電腦去除了程式設計,就成了種障礙。

還好,隨著全球資訊網的發展,每臺裝有現代化瀏覽器的電腦,碰巧就有JavaScript程式設計的環境。本著不用技術細節麻煩使用者的精神,它藏得好好的,但一張網頁就可以讓它展現,並用它來作學習程式設計的平臺。

這就是這本書想要做的。

不憤不啟,不悱不發,舉一隅不以三隅反,則不復也。
—— 孔子

除了講解JavaScript,本書還想要介紹基本的程式設計原則。你會發現,程式設計很難。大多時候,基礎規則簡單清楚。但基於這些基本規則的程式,常會複雜到產生自己的規則和自身的複雜度。正因如此,程式設計極少會簡單可期。正如這個領域的奠基者之一的高德納所說的,這是一門藝術。

要從本書獲益良多,單單讀讀是不夠的。試著仔細看,花些功夫做做練習,直到真正搞懂了才繼續。

程式設計師自創宇宙、自付全責。用計算機程式的方式創造出可以無比複雜的宇宙。
—— Joseph Weizenbaum, 《計算機威力與人類理性》

程式是多面一體。它是程式設計師鍵入的文字,它指導電腦做要做的事,它是計算機記憶體的資料,也控制著對相同記憶體的操作。拿它類比我們熟悉的事物有些牽強,但大致上程式類似一種機器。機械手錶的齒輪巧奪天工地組合在一起,如果表匠夠好,表就可以很多年保持準時。程式的元件也是像這樣結合的,如果程式設計師清楚自己的工作,那程式執行就不會垮掉。

計算機被製造出來,作為這些非物質機器的宿主。計算機自身只能做些蠢笨直接的事情。它們能如此有用,是因為這些事情做得迅即無比。一個精巧地組合了這些簡單操作的程式,可以完成非常複雜的工作。

對某些人而言,程式設計是種令人著迷的遊戲。程式是思維的建築物。不費一文就可以搭建起來,沒有絲毫重量,能夠輕易地成長在我們的按鍵之上。可如果我們玩過頭,那它的龐雜就會失去控制,連造它的人都不能搞定了。這是程式設計的主要問題。這是當今軟體容易垮掉、失效、搞得一團糟的原因。

程式幹活時,它是美麗的。程式設計的藝術是對複雜度的把握。程式大物被制服了,簡自繁中出。

現在,很多程式設計師認為,如果在他們的程式中只使用一塊兒可以透徹理解的技術,就能把複雜度控制到最佳。他們編制了合格程式必須遵守的嚴格規定,他們中的狂熱分子會把違反規定者斥責為“爛”程式設計師。

這是多麼敵視程式設計豐富內涵的行為啊!要將其縮編到某種直接可期的事物,要遮蔽掉所有詭異與美麗的程式。程式設計技術的地平線是那麼廣闊,花樣是那麼紛繁,而且還有大片處女地。那裡自然會散佈著一些圈套和陷坑,誤導不成熟的程式設計師進入各種可怕的誤區,但這些只說明你一定要保持機警,謹慎前行。你會學到,新的挑戰新的疆土一定會出現。不想探索的程式設計師一定會停滯,失去樂趣,不再希望程式設計(而去當了主管)。

據我所知,程式的正確性是其根本標準。效率、清晰和大小也都重要,但如何配置保持均衡則是一種權衡,是每個程式設計師必須自行作出的權衡。經驗法則雖然有用,但也別怕把它打破。

最初,計算機剛誕生時,是沒有程式語言的。程式看起來是這個樣子:

00110001 00000000 00000000
00110001 00000001 00000001
00110011 00000001 00000010
01010001 00001011 00000010
00100010 00000010 00001000
01000011 00000001 00000000
01000001 00000001 00000001
00010000 00000010 00000000
01100010 00000000 00000000

這個程式從一加到十再列印出結果 (1 + 2 + ... + 10 = 55)。它能執行在非常簡單的電腦上。要程式設計早期的計算機,就得把一大排的開關扳到正確的位置,或者在一長條的卡片上打滿孔,再餵給計算機。可以想像要得出這種流程多麼繁瑣,也容易出錯。連寫個簡單的程式都要求要很聰明很自律,複雜點兒的就別想啦。

那些0和1通常稱為位元。當然,手動輸入這些晦澀的位元圖案,確實給程式設計師一種極強的無敵巫師的感覺。從工作滿意度的角度來說,值得這麼幹。

每一行程式都是一條指令。寫成文字是這樣:

  1. 存數0到記憶體格0
  2. 存數1到記憶體格1
  3. 存記憶體格1的值到記憶體格2
  4. 記憶體格2的值減數11
  5. 如果記憶體格2的值是數0, 繼續指令9
  6. 記憶體格0值加上記憶體格1的值
  7. 記憶體格1的值加數1
  8. 繼續指令3
  9. 輸出記憶體格0的值

這比位元湯容易讀些,但也會令人不舒服。使用名字代替指令和記憶體格數字,可能有些幫助:

置‘總數’為0
置‘計數’為1
[兜圈處]
置‘比較’為‘計數’
從‘比較’減11
如‘比較’為0, 從[結束處]繼續
加’計數‘到’總數‘
加1到‘計數’
從[兜圈處]繼續
[結束處]
輸出‘總數’

至此不難看出程式是如何工作的,是吧?前兩行給出兩個記憶體格的開始值:“總數”用來加起程式的結果,“計數”一直跟蹤著我們在用的數。使用“比較”的那幾行可能是最奇怪的。程式想做的,是看“計數”是不是等於11, 這樣才能決定是否該停下來。因為機器太過原始,它只能檢查一個數是不是0, 然後據此做一個判斷(跳轉)。所以它是用標著“比較”的記憶體格,來計算“計數”-11的值然後根據此值做一個決策。下面的兩行把“計數”的值加入結果,然後每次程式決定還沒到11的時候,就給“計數”加一。

此處用Javascript寫這個程式:

var total = 0, count = 1;
while (count <= 10) {
  total += count;
  count += 1;
}
print(total);

這使我們又有所進步。最主要的,是再也沒必要指定程式來回跳動了。魔力字while做到了這點。它持續執行下面的幾行,只要給它的條件沒變:count <= 10,它是指‘count小於或等於10’。顯然,也沒必要創造一個臨時的值來和0比較。這是個笨笨的小細節,而程式語言的力量,就是替我們照顧這些笨笨小小的細節。

最後,如果我們剛好有range和sum這種便捷操作,也就是分別可以建立某個範圍的數集,以及計算某個數集的總和,程式是可以這樣寫的:

print(sum(range(1, 10)));

這個故事的寓意是說,同樣的程式可以寫長或者寫短,能夠讀懂或者不知所云。此程式的第一版最為晦澀,而最終版看著很像英語:列印(print)出總和(sum),範圍(range)從1到10。(稍後章節我們會看到如何能做出sum和range這種東西)。

優秀的程式語言幫助程式設計師用更巨集觀的方式表達自己。它藏起無味的細節,提供便捷的建築模組(例如while結構),並且幾乎總能讓程式設計師自己鑄造模組(例如sum和range操作)。

JavaScript在如今做得大多是些全球資訊網網頁中各種機靈和討厭的事情。一些人聲稱下一版的JavaScript會成為別的工種的重要語言。我不那麼確信這會發生,但只要你在乎程式設計,JavaScript就肯定是種值得學習的語言。即便最後你沒有做什麼Web程式設計,我在此書中展示給你的令人迷幻的程式,會一直跟著你,讓你鬼迷心竅,影響你用其他語言寫的程式。

總有些人說些JavaScript“糟糕”的事。這些事很多確實沒錯。我第一次需要用JavaScript寫點什麼的時候,我幾乎立刻就鄙視了這個語言。它可以全盤接收我鍵入的一切,但卻用非我所願的方式解讀。這當然是因為我自個兒都不懂自己在幹些什麼,但這確實是一件大事:JavaScript極端自由。這種設計的背後是為了讓入門漢程式設計更容易。但實際上,它只是讓你更難發現自己程式的問題,因為系統不會為你指出來。

但是,語言的靈活也是一種優勢。它能完成那些更加僵直的語言無法完成的動作,這可以用來克服JavaScript的一些短處。在適當地學習和使用一段時間之後,我已經喜歡上這門語言了。


與名字的暗示相反,JavaScript幾乎與那個叫Java的程式語言無關。名字的類似出自市場考量,而非真知灼見。1995年Netscape推出JavaScript時,Java正在大造其市也廣受歡迎。顯然,某人覺得搭順風車不賴。而我們現在只好忍著這個名字了。

和JavaScript相關的一個東西稱為ECMAScript。當Netscape之外的瀏覽器開始支援JavaScript或者貌似之物時,一份文件精確地表述了此語言應該做什麼。這份文件描述的語言,在被機構標準化之後,就被稱為ECMAScript了。

ECMAScript描述的是一種通用程式語言,根本沒提如何與網際網路瀏覽器的結合。JavaScript就是ECMAScript,外加一些與網際網路網頁以及瀏覽器視窗打交道的工具。

還有些軟體也使用ECMASCript文件所描述的語言。最重要的是,Flash所用的ActionScript,它基於ECMAScript(但卻沒有精確遵循標準)。Flash的系統用來在網頁上新增可移動的物件,並製造大量噪聲。如果你某天發現自己要學著做做Flash電影,瞭解些JavaScript沒有害處。

JavaScript還在發展。本書寫完之後,ECMAScript5面世了。它和此處描述的版本是相容的,但它添入了一些內建方法,這些功能我們會自己來寫。最新一代的瀏覽器支援這個擴充套件版本的JavaScript。截止到2011年,"ECMAScript harmony",作為一種語言的激進擴充套件,仍在進行標準化。你不必過多擔心這些新版本會讓學自此書的內容過時。原因之一,它們都是現有語言的擴充套件,所以此書所寫的幾乎所有內容都可以保持不變。


此書的絕大部分章節都帶有大量程式碼[1]。我個人經驗是,閱讀和編寫程式碼是學習程式設計的重要一環。不要只是一眼掃過這些示例,要用心讀並加以理解。剛開始會很慢也會很困惑,但很快你就可以把握它了。練習也是一樣。先別假設你明白了,等真正寫出可以幹活的方案再說。

Web的工作方式,使我們總能檢視別人寫在網頁中的JavaScript程式。這可以是學習某事如何完成的好方法。但是因為大部分Web程式設計師不是“職業”程式設計師,或者是些認為JavaScript程式設計太沒勁不值得好好學的人,你這樣查到的大量程式碼,其質量是相當糟糕的。如果學習醜陋或者錯誤的程式碼,那種醜亂就會混進你的程式碼。所以,要小心自己在學誰。


譯者修改了此處console的用法描述,以配合翻譯版的執行環境。

相關文章