來源: ApacheCN『JavaScript 編程精解 中文第三版』翻譯項目原文:Introductionjavascript
譯者:飛龍html
協議:CC BY-NC-SA 4.0java
自豪地採用谷歌翻譯git
部分參考了《JavaScript 編程精解(第 2 版)》程序員
We think we are creating the system for our own purposes. We believe we are making it in our own image... But the computer is not really like us. It is a projection of a very slim part of ourselves: that portion devoted to logic, order, rule, and clarity.github
Ellen Ullman,《Close to the Machine: Technophilia and its Discontents》正則表達式
這是一本關於指導電腦的書。時至今日,計算機就像螺絲刀同樣隨處可見,但相比於螺絲刀而言,計算機更復雜一些,而且,讓他們作你想讓他們作的事情,並不老是那麼容易。數據庫
若是你讓計算機執行的任務是常見的,易於理解的任務,例如向你顯示你的電子郵件,或像計算器同樣工做,則能夠打開相應的應用並開始工做。 但對於獨特的或開放式的任務,應用可能不存在。apache
這就是編程可能出現的地方。編程是構建一個程序的行爲 - 它是一組精確的指令,告訴計算機作什麼。 因爲計算機是愚蠢的,迂腐的野獸,編程從根本上是乏味和使人沮喪的。編程
幸運的是,若是你能夠克服這個事實,而且甚至能夠享受愚蠢機器能夠處理的嚴謹思惟,那麼編程能夠是很是有益的。 它可讓你在幾秒鐘內完成手動操做。 這是一種方法,讓你的電腦工具去作它之前作不到的事情。 它也提供了抽象思惟的優秀練習。
大多數編程都是用編程語言完成的。 編程語言是一種人工構建的語言,用於指導計算機。 有趣的是,咱們發現與電腦溝通的最有效的方式,與咱們彼此溝通的方式相差太大。 與人類語言同樣,計算機語言能夠以新的方式組合詞語和詞組,從而能夠表達新的概念。
在某種程度上,基於語言的界面,例如 80 年代和 90 年代的 BASIC 和 DOS 提示符,是與計算機交互的主要方法。 這些已經在很大程度上被視覺界面取代,這些視覺界面更容易學習,但提供更少的自由。 計算機語言仍然存在,若是你知道在哪裏看到。 每種現代 Web 瀏覽器都內置了一種這樣的語言,即 JavaScript,所以幾乎能夠在全部設備上使用。
本書將試圖讓你足夠了解這門語言,從而完成有用和有趣的東西。
除了講解 JavaScript 以外,本書也會介紹一些程序設計的基本原則。程序設計仍是比較複雜的。編程的基本規則簡單清晰,但在這些基本規則之上構建的程序卻容易變得複雜,致使程序產生了本身的規則和複雜性。即使程序是按照你本身的思路去構建的,你也有可能迷失在代碼之間。
在閱讀本書時,你有可能會以爲書中的概念難以理解。若是你剛剛開始學習編程,那麼你估計還有很多東西須要掌握呢。若是你想將所學知識融會貫通,那麼就須要去多參考和學習一些資料。
是否付出必要的努力徹底取決於你本身。當你閱讀本書的時候發現任何難點,千萬不要輕易就對本身的能力下結論。只要能堅持下去,你就是好樣的。稍作休息,複習一下所學的知識點,始終確保本身閱讀並理解了示例程序和相關的練習。學習是一項艱鉅的任務,但你掌握的全部知識都屬於你本身,並且從此的學習道路會越發輕鬆。
當行動無利可圖時,就收集信息;當信息無利可圖時,就休息。Ursula K. Le Guin,《The Left Hand of Darkness》
一個程序有不少含義:它是開發人員編寫的一段文本、計算機執行的一段指令集合、計算機內存當中的數據以及控制內存中數據的操做集合。咱們一般很難將程序與咱們平常生活中熟悉的事物進行對比。有一種表面上比較恰當的比喻,即將程序視做包含許多組件的機器,爲了讓機器正常工做,這些組件經過內部通訊來實現整個機器的正常運轉。
計算機是一臺物理機器,充當這些非物質機器的載體。計算機自己並不能實現多麼複雜的功能,但計算機之因此有用是由於它們的運算速度很是快。而程序的做用就是將這些看似簡單的動做組合起來,而後實現複雜的功能。
程序是思想的結晶。編寫程序不須要什麼物質投入,它很輕量級,經過咱們的雙手創造。
但若是不稍加註意,程序的體積和複雜度就會失去控制,甚至代碼的編寫者也會感到迷惑。在可控的範圍內編寫程序是編程過程當中首要解決的問題。當程序運行時,一切都是那麼美好。編程的精粹就在於如何更好地控制複雜度。質量高的程序的複雜度都不會過高。
不少開發人員認爲,控制程序複雜度的最好方法就是避免使用不熟悉的技術。他們制定了嚴格的規則(「最佳實踐」),並當心翼翼地呆在他們安全區內。
這不只無聊,並且也是無效的。新問題每每須要新的解決方案。編程領域還很年輕,仍然在迅速發展,而且多樣到足覺得各類不一樣的方法留出空間。在程序設計中有許多可怕的錯誤,你應該繼續犯錯,以便你能理解它們。好的程序看起來是什麼樣的感受,是在實踐中發展的,而不是從一系列規則中學到的。
在計算技術發展伊始,並無編程語言這個概念。程序看起來就像這樣:
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~10 之和,並打印出結果:1+2+...+10=55
。該程序能夠運行在一個簡單的機器上。在早期計算機上編程時,咱們須要在正確的位置設置大量開關陣列,或在紙帶上穿孔並將紙帶輸入計算機中。你能夠想象這個過程是多麼冗長乏味且易於出錯。即使是編寫很是簡單的程序,也須要有經驗的人耗費很大精力才能完成。編寫複雜的程序則更是難上加難。
固然了,手動輸入這些晦澀難懂的位序列(1 和 0)來編寫程序的確能讓程序員感到頗有成就感,並且能給你的職業帶來極大的知足感。
在上面的程序中,每行都包含一條指令。咱們能夠用中文來描述這些指令:
雖然說這已經比一大堆位序列要好讀了許多,但仍然不清晰。使用名稱而不是數字用於指令和存儲位置有所幫助:
Set 「total」 to 0. Set 「count」 to 1. [loop] Set 「compare」 to 「count」. Subtract 11 from 「compare」. If 「compare」 is zero, continue at [end]. Add 「count」 to 「total」. Add 1 to 「count」. Continue at [loop]. [end] Output 「total」.
如今你能看出該程序是如何工做的嗎?前兩行代碼初始化兩個內存位置的值:total
用於保存累加計算結果,而count
則用於記錄當前數字。你可能以爲compare
的那行代碼看起來有些奇怪。程序想根據count
是否等於 11 來決定是否應該中止運行。由於咱們的機器至關原始,因此只能測試一個數字是否爲 0,並根據它作出決策。所以程序用名爲compare
的內存位置存放count–11
的值,並根據該值是否爲 0 決定是否跳轉。接下來兩行將count
的值累加到結果上,並將count
加 1,直到count
等於11
爲止。
下面使用 JavaScript 從新編寫了上面的程序:
let total = 0, count = 1; while (count <= 10) { total += count; count += 1; } console.log(total); // → 55
這個版本的程序獲得了一些改進。更爲重要的是,咱們不再須要指定程序如何來回跳轉了,而是由while
結構負責完成這個任務。只要咱們給予的條件成立,while
語句就會不停地執行其下方的語句塊(包裹在大括號中)。而咱們給予的條件是count<=10
,意思是「count
小於等於 10」。咱們不再須要建立臨時的值並將其與 0 比較,那樣的代碼十分煩瑣。編程語言的一項職責就是,可以幫助咱們處理這些煩瑣無趣的邏輯。
在程序的結尾,也就是while
語句結束後,咱們使用console.log
操做來輸出結果。
最後,咱們剛好有range
和sum
這類方便的操做。下面代碼中的range
函數用於建立數字集合,sum
函數用於計算數字集合之和:
console.log(sum(range(1, 10))); // → 55
咱們能夠從這裏瞭解到,同一個程序的長度可長可短,可讀性可高可低。第一個版本的程序晦澀難懂,而最後一個版本的程序則接近於人類語言的表達方式:將 1~10 範圍內的數字之和記錄下來(咱們會在後面的章節中詳細介紹如何編寫sum
和range
這樣的函數)。
優秀的編程語言能夠爲開發人員提供更高層次的抽象,使用相似於人類語言的方式來與計算機進行交互。它有助於省略細節,提供便捷的積木(好比while
和console.log
),容許你定義本身的積木(好比sum
和range
函數),並使這些積木易於編寫。。
JavaScript 誕生於 1995 年。起初,Netscape Navigator 瀏覽器將其運用在網頁上添加程序。自此之後,各種主流圖形網頁瀏覽器均採用了 JavaScript。JavaScript 使得現代網頁應用程序成爲可能 —— 使用 JavaScript 能夠直接與用戶交互,從而避免每個動做都須要從新載入頁面。但有許多傳統網站也會使用 JavaScript 來提供實時交互以及更加智能的表單功能。
JavaScript 其實和名爲Java的程序設計語言沒有任何關係。起了這麼一個類似的名字徹底是市場考慮使然,這並不是是一個明智的決定。當 JavaScript 出現時,Java 語言已在市場上獲得大力推廣且擁有了極高人氣,所以某些人以爲依附於 Java 的成功是個不錯的主意。而咱們如今已經沒法擺脫這個名字了。
在 JavaScript 被普遍採用以後,ECMA 國際制訂了一份標準文檔來描述 JavaScript 的工做行爲,以便全部聲稱支持 JavaScript 的軟件都使用同一種語言。標準化完成後,該標準被稱爲 ECMAScript 標準。實際上,術語 ECMAScript 和 JavaScript 能夠交換使用。它們不過是同一種語言的兩個名字而已。
許多人會說 JavaScript 語言的壞話。這其中有不少這樣的言論都是正確的。當被要求第一次使用 JavaScript 編寫代碼時,我當時就以爲這門語言難以駕馭。JavaScript 接受我輸入的任何代碼,可是又使用和個人想法徹底不一樣的方式來解釋代碼。因爲我沒有任何線索知道我以前作了什麼,所以我須要作出更多工做,但這也就存在一個實際問題:咱們能夠自由使用 JavaScript,而這種自由卻幾乎沒有限度。這種設計實際上是但願初學者更容易使用 JavaScript 編寫程序。但實際上,系統不會指出咱們錯在何處,所以從程序中找出問題變得更加棘手。
但這種自由性也有其優點,許多技術在更爲嚴格的語言中不可能實現,而在 JavaScript 中則留下了實現的餘地,正如你看到的那樣(好比第十章),有些優點能夠彌補 JavaScript 的一些缺點。在正確地學習 JavaScript 並使用它工做了一段時間後,我真正喜歡上了 JavaScript。
JavaScript 版本衆多。大約在 2000~2010 年間,這正是 JavaScript 飛速發展的時期,瀏覽器支持最多的是 ECMAScript 3。在此期間,ECMA 着手製定 ECMAScript 4,這是一個雄心勃勃的版本,ECMA 計劃在這個版本中加入許多完全的改進與擴展。但因爲 ECMAScript 3 被普遍使用,這種過於激進的修改必然會遭遇重重阻礙,最後 ECMA 不得不於 2008 年放棄了版本 4 的制定。這就產生了不那麼雄心勃勃的版本 5,這只是一些沒有爭議的改進,出如今 2009 年。 而後版本 6 在 2015 年誕生,這是一個重大的更新,其中包括計劃用於版本 4 的一些想法。從那之後,每一年都會有新的更新。
語言不斷髮展的事實意味着,瀏覽器必須不斷跟上,若是你使用的是較老的瀏覽器,它可能不支持每一個特性。 語言設計師會注意,不要作任何可能破壞現有程序的改變,因此新的瀏覽器仍然能夠運行舊的程序。 在本書中,我使用的是 2017 版的 JavaScript。
Web 瀏覽器並非惟一一個能夠運行 JavaScript 的平臺。有些數據庫,好比 MongoDB 和 CouchDB,也使用 JavaScript 做爲腳本語言和查詢語言。一些桌面和服務器開發的平臺,特別是 Node.js 項目(第二十章介紹),爲瀏覽器之外的 JavaScript 編程提供了一個環境。
代碼是程序的文本內容。本書多數章節都介紹了大量代碼。我相信閱讀代碼和編寫代碼是學習編程不可或缺的部分。嘗試不要僅僅看一眼示例,而應該認真閱讀並理解每一個示例。剛開始使用這種方式可能會速度較慢併爲代碼所困惑,但我堅信你很快就能夠熟能生巧。對待習題的方法也應該同樣。除非你確實已經編寫代碼解決了問題,不然不要假設你已經理解了問題。
建議讀者應嘗試在實際的 JavaScript 解釋器中執行習題代碼。這樣一來,你就能夠立刻獲知代碼工做狀況的反饋,並且我但願讀者去作更多的試驗,而不只僅侷限於習題的要求。
能夠在 http://eloquentjavascript.net...,該網址會提供每一個習題的初始代碼,讓你專心於解答習題。
若是想要在本書提供的沙箱之外執行本書代碼,須要稍加註意。許多的示例是獨立的,並且能夠在任何 JavaScript 環境下運行。但後續章節的代碼大多數都是爲特定環境(瀏覽器或者 Node.js)編寫的,並且只能在這些特定環境下執行代碼。此外,許多章節定義了更大的程序,這些章節中出現的代碼片斷會互相依賴或是依賴於一些外部文件。本書網站的沙箱提供了 zip 壓縮文件的連接,該文件包含了全部運行特定章節代碼所需的腳本和數據文件。
本書包括三個部分。前十二章討論 JavaScript 語言自己的一些特性。接下來的 8 章討論網頁瀏覽器和 JavaScript 在網頁編程中的實踐。最後兩章專門講解另外一個使用 JavaScript 編程的環境 —— Node.js。
縱觀本書,共有 5 個項目實戰章,用於講解規模較大的示例程序,你能夠經過這些章來仔細品味真實的編程過程。根據項目出現次序,咱們會陸續構建遞送機器人(7)、程序設計語言(12)、平臺遊戲(16)、像素繪圖程序(19)和一個動態網站(21)。
本書介紹編程語言時,首先使用4章來介紹 JavaScript 語言的基本結構,包括第二章控制結構(好比在本前言中看到的while
單詞)、第三章函數(編寫你本身的積木)和第四章數據結構。此後你就能夠編寫簡單的程序了。接下來,第五章和第六章介紹函數和對象的運用技術,以編寫更加抽象的代碼並以此來控制複雜度。
介紹完第一個項目實戰(7)以後,將會繼續講解語言部分,例如第八章錯誤處理和 bug 修復、第九章正則表達式(處理文本數據的重要工具)、第十章模塊化(解決複雜度的問題)以及第十一章異步編程(處理須要時間的事件)。第二個項目實戰章節(12)則是對本書第一部分的總結。
第二部分(第十三章到第十九章),闡述了瀏覽器 JavaScript 中的一些工具。你將會學到在屏幕上顯示某些元素的方法(第十四章與第十七章),響應用戶輸入的方法(第十五章)和經過網絡通訊的方法(第十八章)。這部分又有兩個項目實戰章節。
此後,第二十章闡述 Node.js,而第二十一章使用該工具構建一個簡單的網頁系統。
本書中存在大量代碼,程序(包括你迄今爲止看到的一些示例)代碼的字體以下所示:
function factorial(n) { if (n == 0) { return 1; } else { return factorial(n - 1) * n; } }
爲了展現程序產生的輸出,本書常在代碼後編寫代碼指望輸出,輸出結果前會加上兩個反斜槓和一個箭頭。
console.log(factorial(8)); // → 40320
祝好運!