JavaScript 是一種輕量級(jí)的腳本語(yǔ)言。所謂“腳本語(yǔ)言”(script language),指的是它不具備開(kāi)發(fā)操作系統(tǒng)的能力,而是只用來(lái)編寫(xiě)控制其他大型應(yīng)用程序(比如瀏覽器)的“腳本”。
JavaScript 也是一種嵌入式(embedded)語(yǔ)言。它本身提供的核心語(yǔ)法不算很多,只能用來(lái)做一些數(shù)學(xué)和邏輯運(yùn)算。JavaScript 本身不提供任何與 I/O(輸入/輸出)相關(guān)的 API,都要靠宿主環(huán)境(host)提供,所以 JavaScript 只合適嵌入更大型的應(yīng)用程序環(huán)境,去調(diào)用宿主環(huán)境提供的底層 API。
目前,已經(jīng)嵌入 JavaScript 的宿主環(huán)境有多種,最常見(jiàn)的環(huán)境就是瀏覽器,另外還有服務(wù)器環(huán)境,也就是 Node 項(xiàng)目。
從語(yǔ)法角度看,JavaScript 語(yǔ)言是一種“對(duì)象模型”語(yǔ)言。各種宿主環(huán)境通過(guò)這個(gè)模型,描述自己的功能和操作接口,從而通過(guò) JavaScript 控制這些功能。但是,JavaScript 并不是純粹的“面向?qū)ο笳Z(yǔ)言”,還支持其他編程范式(比如函數(shù)式編程)。這導(dǎo)致幾乎任何一個(gè)問(wèn)題,JavaScript 都有多種解決方法。閱讀本書(shū)的過(guò)程中,你會(huì)詫異于 JavaScript 語(yǔ)法的靈活性。
JavaScript 的核心語(yǔ)法部分相當(dāng)精簡(jiǎn),只包括兩個(gè)部分:基本的語(yǔ)法構(gòu)造(比如操作符、控制結(jié)構(gòu)、語(yǔ)句)和標(biāo)準(zhǔn)庫(kù)(就是一系列具有各種功能的對(duì)象比如Array
、Date
、Math
等)。除此之外,各種宿主環(huán)境提供額外的 API(即只能在該環(huán)境使用的接口),以便 JavaScript 調(diào)用。以瀏覽器為例,它提供的額外 API 可以分成三大類。
如果宿主環(huán)境是服務(wù)器,則會(huì)提供各種操作系統(tǒng)的 API,比如文件操作 API、網(wǎng)絡(luò)通信 API等等。這些你都可以在 Node 環(huán)境中找到。
本書(shū)主要介紹 JavaScript 核心語(yǔ)法和瀏覽器網(wǎng)頁(yè)開(kāi)發(fā)的基本知識(shí),不涉及 Node。全書(shū)可以分成以下四大部分。
JavaScript 語(yǔ)言有多個(gè)版本。本書(shū)的內(nèi)容主要基于 ECMAScript 5.1 版本,這是學(xué)習(xí) JavaScript 語(yǔ)法的基礎(chǔ)。ES6 和更新的語(yǔ)法請(qǐng)參考我寫(xiě)的《ECMAScript 6入門(mén)》。
JavaScript 語(yǔ)言有一些顯著特點(diǎn),使得它非常值得學(xué)習(xí)。它既適合作為學(xué)習(xí)編程的入門(mén)語(yǔ)言,也適合當(dāng)作日常開(kāi)發(fā)的工作語(yǔ)言。它是目前最有希望、前途最光明的計(jì)算機(jī)語(yǔ)言之一。
JavaScript 的發(fā)明目的,就是作為瀏覽器的內(nèi)置腳本語(yǔ)言,為網(wǎng)頁(yè)開(kāi)發(fā)者提供操控瀏覽器的能力。它是目前唯一一種通用的瀏覽器腳本語(yǔ)言,所有瀏覽器都支持。它可以讓網(wǎng)頁(yè)呈現(xiàn)各種特殊效果,為用戶提供良好的互動(dòng)體驗(yàn)。
目前,全世界幾乎所有網(wǎng)頁(yè)都使用 JavaScript。如果不用,網(wǎng)站的易用性和使用效率將大打折扣,無(wú)法成為操作便利、對(duì)用戶友好的網(wǎng)站。
對(duì)于一個(gè)互聯(lián)網(wǎng)開(kāi)發(fā)者來(lái)說(shuō),如果你想提供漂亮的網(wǎng)頁(yè)、令用戶滿意的上網(wǎng)體驗(yàn)、各種基于瀏覽器的便捷功能、前后端之間緊密高效的聯(lián)系,JavaScript 是必不可少的工具。
近年來(lái),JavaScript 的使用范圍,慢慢超越了瀏覽器,正在向通用的系統(tǒng)語(yǔ)言發(fā)展。
(1)瀏覽器的平臺(tái)化
隨著 HTML5 的出現(xiàn),瀏覽器本身的功能越來(lái)越強(qiáng),不再僅僅能瀏覽網(wǎng)頁(yè),而是越來(lái)越像一個(gè)平臺(tái),JavaScript 因此得以調(diào)用許多系統(tǒng)功能,比如操作本地文件、操作圖片、調(diào)用攝像頭和麥克風(fēng)等等。這使得 JavaScript 可以完成許多以前無(wú)法想象的事情。
(2)Node
Node 項(xiàng)目使得 JavaScript 可以用于開(kāi)發(fā)服務(wù)器端的大型項(xiàng)目,網(wǎng)站的前后端都用 JavaScript 開(kāi)發(fā)已經(jīng)成為了現(xiàn)實(shí)。有些嵌入式平臺(tái)(Raspberry Pi)能夠安裝 Node,于是 JavaScript 就能為這些平臺(tái)開(kāi)發(fā)應(yīng)用程序。
(3)數(shù)據(jù)庫(kù)操作
JavaScript 甚至也可以用來(lái)操作數(shù)據(jù)庫(kù)。NoSQL 數(shù)據(jù)庫(kù)這個(gè)概念,本身就是在 JSON(JavaScript Object Notation)格式的基礎(chǔ)上誕生的,大部分 NoSQL 數(shù)據(jù)庫(kù)允許 JavaScript 直接操作?;?SQL 語(yǔ)言的開(kāi)源數(shù)據(jù)庫(kù) PostgreSQL 支持 JavaScript 作為操作語(yǔ)言,可以部分取代 SQL 查詢語(yǔ)言。
(4)移動(dòng)平臺(tái)開(kāi)發(fā)
JavaScript 也正在成為手機(jī)應(yīng)用的開(kāi)發(fā)語(yǔ)言。一般來(lái)說(shuō),安卓平臺(tái)使用 Java 語(yǔ)言開(kāi)發(fā),iOS 平臺(tái)使用 Objective-C 或 Swift 語(yǔ)言開(kāi)發(fā)。許多人正在努力,讓 JavaScript 成為各個(gè)平臺(tái)的通用開(kāi)發(fā)語(yǔ)言。
PhoneGap 項(xiàng)目就是將 JavaScript 和 HTML5 打包在一個(gè)容器之中,使得它能同時(shí)在 iOS 和安卓上運(yùn)行。Facebook 公司的 React Native 項(xiàng)目則是將 JavaScript 寫(xiě)的組件,編譯成原生組件,從而使它們具備優(yōu)秀的性能。
Mozilla 基金會(huì)的手機(jī)操作系統(tǒng) Firefox OS,更是直接將 JavaScript 作為操作系統(tǒng)的平臺(tái)語(yǔ)言,但是很可惜這個(gè)項(xiàng)目沒(méi)有成功。
(5)內(nèi)嵌腳本語(yǔ)言
越來(lái)越多的應(yīng)用程序,將 JavaScript 作為內(nèi)嵌的腳本語(yǔ)言,比如 Adobe 公司的著名 PDF 閱讀器 Acrobat、Linux 桌面環(huán)境 GNOME 3。
(6)跨平臺(tái)的桌面應(yīng)用程序
Chromium OS、Windows 8 等操作系統(tǒng)直接支持 JavaScript 編寫(xiě)應(yīng)用程序。Mozilla 的 Open Web Apps 項(xiàng)目、Google 的 Chrome App 項(xiàng)目、GitHub 的 Electron 項(xiàng)目、以及 TideSDK 項(xiàng)目,都可以用來(lái)編寫(xiě)運(yùn)行于 Windows、Mac OS 和 Android 等多個(gè)桌面平臺(tái)的程序,不依賴瀏覽器。
(7)小結(jié)
可以預(yù)期,JavaScript 最終將能讓你只用一種語(yǔ)言,就開(kāi)發(fā)出適應(yīng)不同平臺(tái)(包括桌面端、服務(wù)器端、手機(jī)端)的程序。早在2013年9月的統(tǒng)計(jì)之中,JavaScript 就是當(dāng)年 GitHub 上使用量排名第一的語(yǔ)言。
著名程序員 Jeff Atwood 甚至提出了一條 “Atwood 定律”:
“所有可以用 JavaScript 編寫(xiě)的程序,最終都會(huì)出現(xiàn) JavaScript 的版本。”(Any application that can be written in JavaScript will eventually be written in JavaScript.)
相比學(xué)習(xí)其他語(yǔ)言,學(xué)習(xí) JavaScript 有一些有利條件。
(1)學(xué)習(xí)環(huán)境無(wú)處不在
只要有瀏覽器,就能運(yùn)行 JavaScript 程序;只要有文本編輯器,就能編寫(xiě) JavaScript 程序。這意味著,幾乎所有電腦都原生提供 JavaScript 學(xué)習(xí)環(huán)境,不用另行安裝復(fù)雜的 IDE(集成開(kāi)發(fā)環(huán)境)和編譯器。
(2)簡(jiǎn)單性
相比其他腳本語(yǔ)言(比如 Python 或 Ruby),JavaScript 的語(yǔ)法相對(duì)簡(jiǎn)單一些,本身的語(yǔ)法特性并不是特別多。而且,那些語(yǔ)法中的復(fù)雜部分,也不是必需要學(xué)會(huì)。你完全可以只用簡(jiǎn)單命令,完成大部分的操作。
(3)與主流語(yǔ)言的相似性
JavaScript 的語(yǔ)法很類似 C/C++ 和 Java,如果學(xué)過(guò)這些語(yǔ)言(事實(shí)上大多數(shù)學(xué)校都教),JavaScript 的入門(mén)會(huì)非常容易。
必須說(shuō)明的是,雖然核心語(yǔ)法不難,但是 JavaScript 的復(fù)雜性體現(xiàn)在另外兩個(gè)方面。
首先,它涉及大量的外部 API。JavaScript 要發(fā)揮作用,必須與其他組件配合,這些外部組件五花八門(mén),數(shù)量極其龐大,幾乎涉及網(wǎng)絡(luò)應(yīng)用的各個(gè)方面,掌握它們絕非易事。
其次,JavaScript 語(yǔ)言有一些設(shè)計(jì)缺陷。某些地方相當(dāng)不合理,另一些地方則會(huì)出現(xiàn)怪異的運(yùn)行結(jié)果。學(xué)習(xí) JavaScript,很大一部分時(shí)間是用來(lái)搞清楚哪些地方有陷阱。Douglas Crockford 寫(xiě)過(guò)一本有名的書(shū),名字就叫《JavaScript: The Good Parts》,言下之意就是這門(mén)語(yǔ)言不好的地方很多,必須寫(xiě)一本書(shū)才能講清楚。另外一些程序員則感到,為了更合理地編寫(xiě) JavaScript 程序,就不能用 JavaScript 來(lái)寫(xiě),而必須發(fā)明新的語(yǔ)言,比如 CoffeeScript、TypeScript、Dart 這些新語(yǔ)言的發(fā)明目的,多多少少都有這個(gè)因素。
盡管如此,目前看來(lái),JavaScript 的地位還是無(wú)法動(dòng)搖。加之,語(yǔ)言標(biāo)準(zhǔn)的快速進(jìn)化,使得 JavaScript 功能日益增強(qiáng),而語(yǔ)法缺陷和怪異之處得到了彌補(bǔ)。所以,JavaScript 還是值得學(xué)習(xí),況且它的入門(mén)真的不難。
JavaScript 的性能優(yōu)勢(shì)體現(xiàn)在以下方面。
(1)靈活的語(yǔ)法,表達(dá)力強(qiáng)。
JavaScript 既支持類似 C 語(yǔ)言清晰的過(guò)程式編程,也支持靈活的函數(shù)式編程,可以用來(lái)寫(xiě)并發(fā)處理(concurrent)。這些語(yǔ)法特性已經(jīng)被證明非常強(qiáng)大,可以用于許多場(chǎng)合,尤其適用異步編程。
JavaScript 的所有值都是對(duì)象,這為程序員提供了靈活性和便利性。因?yàn)槟憧梢院芊奖愕?、按照需要隨時(shí)創(chuàng)造數(shù)據(jù)結(jié)構(gòu),不用進(jìn)行麻煩的預(yù)定義。
JavaScript 的標(biāo)準(zhǔn)還在快速進(jìn)化中,并不斷合理化,添加更適用的語(yǔ)法特性。
(2)支持編譯運(yùn)行。
JavaScript 語(yǔ)言本身,雖然是一種解釋型語(yǔ)言,但是在現(xiàn)代瀏覽器中,JavaScript 都是編譯后運(yùn)行。程序會(huì)被高度優(yōu)化,運(yùn)行效率接近二進(jìn)制程序。而且,JavaScript 引擎正在快速發(fā)展,性能將越來(lái)越好。
此外,還有一種 WebAssembly 格式,它是 JavaScript 引擎的中間碼格式,全部都是二進(jìn)制代碼。由于跳過(guò)了編譯步驟,可以達(dá)到接近原生二進(jìn)制代碼的運(yùn)行速度。各種語(yǔ)言(主要是 C 和 C++)通過(guò)編譯成 WebAssembly,就可以在瀏覽器里面運(yùn)行。
(3)事件驅(qū)動(dòng)和非阻塞式設(shè)計(jì)。
JavaScript 程序可以采用事件驅(qū)動(dòng)(event-driven)和非阻塞式(non-blocking)設(shè)計(jì),在服務(wù)器端適合高并發(fā)環(huán)境,普通的硬件就可以承受很大的訪問(wèn)量。
JavaScript 是一種開(kāi)放的語(yǔ)言。它的標(biāo)準(zhǔn) ECMA-262 是 ISO 國(guó)際標(biāo)準(zhǔn),寫(xiě)得非常詳盡明確;該標(biāo)準(zhǔn)的主要實(shí)現(xiàn)(比如 V8 和 SpiderMonkey 引擎)都是開(kāi)放的,而且質(zhì)量很高。這保證了這門(mén)語(yǔ)言不屬于任何公司或個(gè)人,不存在版權(quán)和專利的問(wèn)題。
語(yǔ)言標(biāo)準(zhǔn)由 TC39 委員會(huì)負(fù)責(zé)制定,該委員會(huì)的運(yùn)作是透明的,所有討論都是開(kāi)放的,會(huì)議記錄都會(huì)對(duì)外公布。
不同公司的 JavaScript 運(yùn)行環(huán)境,兼容性很好,程序不做調(diào)整或只做很小的調(diào)整,就能在所有瀏覽器上運(yùn)行。
全世界程序員都在使用 JavaScript,它有著極大的社區(qū)、廣泛的文獻(xiàn)和圖書(shū)、豐富的代碼資源。絕大部分你需要用到的功能,都有多個(gè)開(kāi)源函數(shù)庫(kù)可供選用。
作為項(xiàng)目負(fù)責(zé)人,你不難招聘到數(shù)量眾多的 JavaScript 程序員;作為開(kāi)發(fā)者,你也不難找到一份 JavaScript 的工作。
本教程包含大量的示例代碼,只要電腦安裝了瀏覽器,就可以用來(lái)實(shí)驗(yàn)了。讀者可以一邊讀一邊運(yùn)行示例,加深理解。
推薦安裝 Chrome 瀏覽器,它的“開(kāi)發(fā)者工具”(Developer Tools)里面的“控制臺(tái)”(console),就是運(yùn)行 JavaScript 代碼的理想環(huán)境。
進(jìn)入 Chrome 瀏覽器的“控制臺(tái)”,有兩種方法。
Option + Command + J
(Mac)或者Ctrl + Shift + J
(Windows / Linux)Option + Command + I
(Mac)以及Ctrl + Shift + I
(Windows / Linux),然后選擇 Console 面板
進(jìn)入控制臺(tái)以后,就可以在提示符后輸入代碼,然后按Enter
鍵,代碼就會(huì)執(zhí)行。如果按Shift + Enter
鍵,就是代碼換行,不會(huì)觸發(fā)執(zhí)行。建議閱讀本教程時(shí),將代碼復(fù)制到控制臺(tái)進(jìn)行實(shí)驗(yàn)。
作為嘗試,你可以將下面的程序復(fù)制到“控制臺(tái)”,按下回車后,就可以看到運(yùn)行結(jié)果。
function greetMe(yourName) {
console.log('Hello ' + yourName);
}
greetMe('World')
// Hello World
更多建議: