圖靈社區(qū)會員 StinkBC(StinkBC@gmail.com) 專享 尊重版權(quán)
圖靈社區(qū)會員 StinkBC(StinkBC@gmail.com) 專享 尊重版權(quán)
圖靈社區(qū)會員 StinkBC(StinkBC@gmail.com) 專享 尊重版權(quán)
內(nèi) 容 提 要
本書是 JavaScript 超級暢銷書的最新版。ECMAScript 5 和 HTML5 在標準之爭中雙雙勝出,使大量
專有實現(xiàn)和客戶端擴展正式進入規(guī)范,同時也為 JavaScript 增添了很多適應未來發(fā)展的新特性。本書這
一版除增加 5 章全新內(nèi)容外,其他章節(jié)也有較大幅度的增補和修訂,新內(nèi)容篇幅約占三分之一。全書從
JavaScript 語言實現(xiàn)的各個組成部分——語言核心、DOM、BOM、事件模型講起,深入淺出地探討了面向
對象編程、Ajax 與 Comet 服務器端通信,HTML5 表單、媒體、Canvas(包括 WebGL)及 Web Workers、
地理定位、跨文檔傳遞消息、客戶端存儲(包括 IndexedDB)等新 API,還介紹了離線應用和與維護、性
能、部署相關(guān)的最佳開發(fā)實踐。本書附錄展望了未來的 API 和 ECMAScript Harmony 規(guī)范。
本書適合有一定編程經(jīng)驗的 Web 應用開發(fā)人員閱讀,也可作為高校及社會實用技術(shù)培訓相關(guān)專業(yè)課
程的教材。
圖靈程序設計叢書
JavaScript高級程序設計(第3版)
定價:99.00元
讀者服務熱線:(010)51095186轉(zhuǎn)604 印裝質(zhì)量熱線:(010)67129223
反盜版熱線:(010)67171154
著 [美] Nicholas C. Zakas
譯 李松峰 曹 力
責任編輯 朱 巍
人民郵電出版社出版發(fā)行 北京市崇文區(qū)夕照寺街14號
郵編 100061 電子郵件 315@ptpress.com.cn
網(wǎng)址 http://www.ptpress.com.cn
北京 印刷
開本:800×1000 1/16
印張:46.75 彩插:8
字數(shù):1092千字 2012年3 月第1版
印數(shù):1 — 6 000冊 2012年3月北京第1次印刷
著作權(quán)合同登記號 圖字:01-2012-1175 號
ISBN 978-7-115-27579-0
◆
◆
◆
圖靈社區(qū)會員 StinkBC(StinkBC@gmail.com) 專享 尊重版權(quán)
錯誤!文檔中沒有指定樣式的文字。 1
1
2
3
4
5
13
6
7
8
9
10
11
12
版 權(quán) 聲 明
Original edition, entitled Professional JavaScript for Web Developers 3rd Edition, by Nicholas C. Zakas,
ISBN 978-1-118-02669-4, published by John Wiley & Sons, Inc.
Copyright ?2012 by John Wiley & Sons, Inc.,All rights reserved.This translation published under License.
Translation edition published by POSTS & TELECOM PRESS Copyright ?2012.
Copies of this book sold without a Wiley sticker on the cover are unauthorized and illegal.
本書簡體中文版由 John Wiley & Sons, Inc.授權(quán)人民郵電出版社獨家出版。
本書封底貼有 John Wiley & Sons, Inc.激光防偽標簽,無標簽者不得銷售。
版權(quán)所有,侵權(quán)必究。
圖靈社區(qū)會員 StinkBC(StinkBC@gmail.com) 專享 尊重版權(quán)
4 第 5 章 IDA 數(shù)據(jù)顯示窗口
序
20 多年的職業(yè)生涯,我也長出了白頭發(fā)?;厥淄?,曾經(jīng)對我的職業(yè)道路產(chǎn)生過重要影響的技術(shù)和
人歷歷在目。如果讓我只說一種技術(shù),一種對我產(chǎn)生了最大正面影響的技術(shù),那么就是 JavaScript。說
實話,我也并非一直都是 JavaScript 的信徒。跟許多人一樣,我以前也把它當作一門玩具語言,認為它
只能用來做一些旋轉(zhuǎn)的橫幅廣告,或者在頁面中添加一些有意思的交互效果作為裝飾。我原來是做服務
器端開發(fā)的,我們都對這種玩具語言不感冒,該死的!可是,后來 Ajax 出現(xiàn)了。
永遠也忘不了當時無孔不入的 Ajax,大家都認為它是一種非常酷、非常新,同時極具創(chuàng)造性的技術(shù)。
我也開始了解它,閱讀相關(guān)資料。知道這門曾被我嗤之以鼻的玩具語言如今被每一位專業(yè) Web 開發(fā)人
員津津樂道之后,我感到很震驚。突然,我的看法就轉(zhuǎn)變了。隨著探索 Ajax 的繼續(xù)深入,我認識到
JavaScript 的強大威力,急切地想了解它能提供的所有“法寶”。于是,我全身心地投入到學習 JavaScript
之中,不僅努力學習這門語言,還加入了 jQuery 項目團隊,專門從事客戶端開發(fā)。我的日子過得很爽。
對 JavaScript 了解得越深,接觸的開發(fā)人員就越多,其中不乏今天在我眼里依然是巨星和導師級的
人物。尼古拉斯·澤卡斯(本書作者)就是這樣一位開發(fā)人員。我一直記得在讀本書第 2 版時心中油然
而生的喜悅之情,雖然我也有多年的積累,但仍然從中學到了很多新東西。這本書實實在在、深入淺出,
讀來就好像尼古拉斯對不同層次的讀者都了如指掌,所以他的風格才那么貼切自然。對于技術(shù)書來說,
這是非常突出的一個特色。多數(shù)作者都想靠堅深的技術(shù)給人留下印象,但這本書不同。所以,它很快就
成為了我案頭必備的書,我也會向那些有志全面掌握 JavaScript 的開發(fā)人員推薦這本書。我希望每個人
對這本書都能有跟我一樣的體會,認識到它的價值所在。
后來,在一次jQuery大會上,我榮幸地見到了尼古拉斯本人。站在我面前的是一位世界頂級的JavaScript
開發(fā)人員,而且正負責世界上最重要的一個 Web 站點(雅虎)。尼古拉斯是我見過的最隨和的人之一。真
的,見到他的時候我有一種追星族的幻覺。但他就是那么一個活生生的人,一個想幫助開發(fā)人員成就夢想
的人。不僅他的書改變了我對 JavaScript 的認識,而且尼古拉斯這個人,也讓我愿意接近,愿意了解。
聽說尼古拉斯要請我作序,我激動得不知道說什么才好。在此,我代表大牛來為本書暖場。這個序
也是他本人有多么令人景仰的一個明證。不過,更重要的是,這也給了我一個機會,讓我能跟大家分享
自己為什么覺得這本書如此重要。我看過很多 JavaScript 圖書,的確也有很多令人嘆服的佳作。但在我
看來,這本書為讀者成為全方位的 JavaScript 高手提供了“一攬子方案”。
這本書從介紹表達式和變量聲明開始,平滑地過渡到了閉包、面向?qū)ο箝_發(fā)等高級主題。與那些把
大量篇幅花在講解背景知識上的書,以及那些讓人感覺好像是要使用 JavaScript 開發(fā)導彈制導系統(tǒng)的書
相比,這本書讓人感覺細致周到、親切自然。這是一本寫給“普通人”的書,它能讓你編寫出引以為榮
的代碼,構(gòu)建出令人叫絕的網(wǎng)站。
雷·邦戈(Rey Bango)
微軟公司高級布道師,jQuery 項目團隊核心成員
圖靈社區(qū)會員 StinkBC(StinkBC@gmail.com) 專享 尊重版權(quán)
前 言 1
1
2
3
4
5
13
6
7
8
9
10
11
12
前 言
從驅(qū)動全球商業(yè)、貿(mào)易及管理領域不計其數(shù)的復雜應用程序的角度來看,說 JavaScript 已經(jīng)成為當
今世界上最流行的編程語言一點兒都不為過。
JavaScript 是一種非常松散的面向?qū)ο笳Z言,也是 Web 開發(fā)中極受歡迎的一門語言。JavaScript,盡
管它的語法和編程風格與 Java 都很相似,但它卻不是 Java 的“輕量級”版本,甚至與 Java 沒有任何關(guān)
系。JavaScript 是一種全新的動態(tài)語言,它植根于全球數(shù)億網(wǎng)民都在使用的 Web 瀏覽器之中,致力于增
強網(wǎng)站和 Web 應用程序的交互性。
在本書中,我們將對 JavaScript 追根溯源,從它在最早的 Netscape 瀏覽器中誕生談起,一直談到今
天的它對 DOM 和 Ajax 的強大支持。讀者將通過本書掌握如何運用和擴展這門語言,從而更好地滿足自
己的需求,以及如何實現(xiàn)客戶端與服務器的無縫通信,而又不必求助于 Java 或隱藏的網(wǎng)頁框架(frame
元素)。一言以蔽之,本書將教會你在面對各種常見的 Web 開發(fā)問題時,如何拿出自己的 JavaScript 解
決方案。
本書讀者對象
本書將下列三類人員作為目標讀者:
(1) 熟悉面向?qū)ο缶幊?、?jīng)驗豐富而又打算學習 JavaScript 的開發(fā)人員,JavaScript 畢竟與 Java、C++
等傳統(tǒng) OO 語言存在著諸多聯(lián)系;
(2) 有意提升自己網(wǎng)站和 Web 應用程序易用性的 Web 開發(fā)人員;
(3) 希望全面深入地理解這門語言的初級 JavaScript 開發(fā)人員。
此外,本書也適合熟悉下列相關(guān)技術(shù)的讀者閱讀:
(1) Java
(2) PHP
(3) ASP.NET
(4) HTML
(5) CSS
(6) XML
本書不適合沒有計算機基礎知識的初學者,也不適合只想為網(wǎng)站添加簡單交互功能的讀者。建議這
些朋友學習閱讀 Beginning JavaScript, 3rd Edition(Wiley, 2007)一書①。
——————————
① 本書中文版《JavaScript 入門經(jīng)典(第 3 版)》已經(jīng)由清華大學出版社出版?!g者注(以下腳注如無特殊說明,
均為譯者注)
獻給我的父母,是他們永遠給我支持和鼓勵。
圖靈社區(qū)會員 StinkBC(StinkBC@gmail.com) 專享 尊重版權(quán)
2 前 言
本書內(nèi)容
本書提供了 JavaScript 開發(fā)人員必須掌握的內(nèi)容,全面涵蓋了 JavaScript 的各種高級、有用的特性。
本書首先介紹了 JavaScript 的起源及其發(fā)展現(xiàn)狀,隨后討論了構(gòu)成 JavaScript 實現(xiàn)的各個組成部分,
重點講解了 ECMAScript 和 DOM 標準。此外,還對不同 Web 瀏覽器的 JavaScript 實現(xiàn)之間存在的差異,
給出了相應的說明。
在此基礎上,本書從講解 JavaScript 的基本概念入手,探討了 JavaScript 面向?qū)ο蟪绦蛟O計和繼承的
方式,以及如何在 HTML 等標記語言中使用它。在深入剖析了事件和事件處理之后,又解釋了各種瀏
覽器檢測技術(shù)。本書還探討了 HTML5、Selectors API 和 File API 等一系列新 API。
本書最后一部分專門討論了高級主題,涉及性能和內(nèi)存優(yōu)化、最佳實踐以及對 JavaScript 未來的
展望。
本書結(jié)構(gòu)
本書共 25 章,各章簡介如下。
第 1 章“JavaScript 簡介”,講述了 JavaScript 的起源:因何而生,如何發(fā)展,現(xiàn)狀如何。涉及的
概念主要有 JavaScript 與 ECMAScript 之間的關(guān)系、DOM(Document Object Model,文檔對象模型)、
BOM(Browser Object Model,瀏覽器對象模型)。此外,還將討論 ECMA(European Computer
Manufacturer’s Association,歐洲計算機制造商協(xié)會)和 W3C(World Wide Web Consortium,萬維網(wǎng)聯(lián)
盟)制定的一些相關(guān)標準。
第 2 章“在 HTML 中使用 JavaScript”,介紹了如何在 HTML 中使用 JavaScript 創(chuàng)建動態(tài)網(wǎng)頁。
這一章不僅展示了在網(wǎng)頁中嵌入 JavaScript 的各種方式,還討論了 JavaScript 內(nèi)容類型(content-type)及
其與<script>元素的關(guān)系。
第 3 章“基本概念”,討論了 JavaScript 語言的基本概念,包括語法和流控制語句。這一章也分析
了 JavaScript 與其他基于 C 的語言在語法上的相同和不同之處,還介紹了與內(nèi)置操作符有關(guān)的類型轉(zhuǎn)換
問題。
第 4 章“變量、作用域和內(nèi)存問題”,探討了 JavaScript 如何處理其松散類型的變量。這一章還討
論了原始值和引用值之間的差別,以及與變量有關(guān)的執(zhí)行環(huán)境的相應內(nèi)容。最后,通過介紹 JavaScript
的垃圾收集機制,解釋了變量在退出作用域時釋放其內(nèi)存的問題。
第 5 章“引用類型”,詳盡介紹了 JavaScript 內(nèi)置的所有引用類型,如 Object 和 Array。這一
章對 ECMA-262 規(guī)范中描述的每一種引用類型既做了理論上的闡釋,又從瀏覽器實現(xiàn)的角度給出了
介紹。
第 6 章“面向?qū)ο蟮某绦蛟O計”,講述了在 JavaScript 中如何實現(xiàn)面向?qū)ο蟮某绦蛟O計。由于
JavaScript 沒有類的概念,因此這一章從對象創(chuàng)建和繼承的層面上展示了一些流行的技術(shù)。此外,這一
章還講解了函數(shù)原型的概念,并對函數(shù)原型與整個面向?qū)ο蠓椒ǖ年P(guān)系進行了探討。
第 7 章“函數(shù)表達式”,集中介紹了 JavaScript 中最為強大的一個特性——函數(shù)表達式。相關(guān)的內(nèi)
容涉及閉包、this 對象的角色、模塊模式和創(chuàng)建私有對象成員等。
第 8 章“BOM”,介紹 BOM(Browser Object Model,瀏覽器對象模型),即負責處理與瀏覽器自
身有關(guān)的交互操作的對象集合。這一章全面介紹了每一個 BOM 對象,包括 window、document、
圖靈社區(qū)會員 StinkBC(StinkBC@gmail.com) 專享 尊重版權(quán)
前 言 3
1
2
3
4
5
13
6
7
8
9
10
11
12
location、navigator 和 screen。
第 9 章“客戶端檢測”,討論了檢測客戶端機器及其支持特性的各種手段,包括特性檢測及用戶代
理字符串檢測的不同技術(shù)。這一章還就每種手段的優(yōu)缺點及適用情形給出了詳細說明。
第 10 章“DOM”,介紹 DOM(Document Object Model,文檔對象模型),即 DOM1 規(guī)定的 JavaScript
中的 DOM 對象。這一章也簡要介紹了 XML 及其與 DOM 的關(guān)系,為深入探討所有 DOM 規(guī)范及其定義
的操作網(wǎng)頁的方式奠定了基礎。
第 11 章“DOM 擴展”,介紹了其他 API 以及瀏覽器本身為 DOM 添加的各種功能。涉及內(nèi)容包括
Selectors API、Element Traversal API 和 HTML5 擴展。
第 12 章“DOM2 和 DOM3”,在前兩章的基礎上繼續(xù)探討了 DOM2 和 DOM3 中新增的 DOM 屬
性、方法和對象。這一章還討論了 IE 與其他瀏覽器的兼容性問題。
第 13 章“事件”,解釋了 JavaScript 中事件的本質(zhì),對遺留機制的支持,以及 DOM 對事件機制的
重新定義。這一章討論了多種設備,包括 Wii 和 iPhone。
第 14 章“表單腳本”,講述如何使用 JavaScript 增強表單的交互性,突破瀏覽器的局限性。這一
章的討論主要圍繞單個表單元素如文本框、選擇框,以及圍繞數(shù)據(jù)驗證和操作展開。
第 15 章“使用 Canvas 繪圖”,討論了<canvas>標簽以及如何通過它來動態(tài)繪圖。不僅涵蓋 2D
上下文,也將討論 WebGL(3D)上下文,可以為創(chuàng)建動畫和游戲夯實基礎。
第 16 章“HTML5 腳本編程”,介紹了 HTML5 規(guī)定的 JavaScript API,涉及跨文檔傳遞消息、拖
放 API 和以編程方式控制<audio>和<video>元素,以及管理歷史狀態(tài)。
第 17 章“錯誤處理與調(diào)試”,討論瀏覽器如何處理 JavaScript 代碼錯誤,并展示了一些處理錯誤
的方式。這一章針對每種瀏覽器分別討論了相應的調(diào)試工具和技術(shù),還給出了簡化調(diào)試工作的建議。
第 18 章“JavaScript 與 XML”,展示了 JavaScript 中用于讀取和操作 XML(eXtensible Markup
Language,可擴展標記語言)的特性。這一章分析了不同瀏覽器提供的 XML 支持和對象的差異,給出
了編寫跨瀏覽器代碼的簡易方法。此外,這一章還介紹了用于在客戶端轉(zhuǎn)換XML數(shù)據(jù)的XSLT(eXtensible
Stylesheet Language Transformations,可擴展樣式表語言轉(zhuǎn)換)技術(shù)。
第 19 章“E4X”,討論了 E4X(ECMAScript for XML,ECMAScript 中的 XML 擴展);設計 E4X 的
出發(fā)點是簡化 XML 處理任務。這一章探討了在處理 XML 時,使用 E4X 與使用 DOM 相比有哪些
優(yōu)勢。
第 20 章“JSON”,介紹了作為 XML 替代格式的 JSON,包含瀏覽器原生支持的 JSON 解析和序
列化,以及使用 JSON 時要注意的安全問題。
第 21 章“Ajax 與 Comet”,講解了常用的 Ajax 技術(shù),包括使用 XMLHttpRequest 對象及 CORS
(Cross-Origin Resource Sharing,跨來源資源共享)API 實現(xiàn)跨域 Ajax 通信。這一章展示了瀏覽器在實
現(xiàn)與支持方面存在的差異,同時也給出了一些使用建議。
第 22 章“高級技巧”,深入講解了一些 JavaScript 中較復雜的模式,包括函數(shù)柯里化(currying)、
部分函數(shù)應用和動態(tài)函數(shù)。這一章還討論了如何創(chuàng)建自定義的事件框架和使用 ECMAScript 5 創(chuàng)建防篡
改對象。
第 23 章“離線應用與客戶端存儲”,討論了如何檢測應用離線以及在客戶端機器中存儲數(shù)據(jù)的各
種技術(shù)。先從受到最廣泛支持的特性 cookie 談起,繼而介紹了新興的客戶端存儲技術(shù),如 Web Storage
和 IndexedDB。
圖靈社區(qū)會員 StinkBC(StinkBC@gmail.com) 專享 尊重版權(quán)
4 前 言
第 24 章“最佳實踐”,探討了在企業(yè)級環(huán)境中使用 JavaScript 的各種方式。其中,著眼于提高可
維護性的內(nèi)容包括編碼技巧、格式化和通用編程實踐。這一章還介紹了改善代碼執(zhí)行性能及速度優(yōu)化的
一些技術(shù)。最后討論了部署問題,包括如何創(chuàng)建構(gòu)建過程。
第 25 章“新興的 API”,介紹了為增強瀏覽器中的 JavaScript 而創(chuàng)建的新 API。雖然這些 API 還沒
有得到完整或全面的支持,但它們已經(jīng)嶄露頭角,有些瀏覽器也已經(jīng)部分地實現(xiàn)了這些 API。這一章的
內(nèi)容主要是 Web 計時和文件 API。
使用示例
要運行本書中的示例,需要安裝下列軟件:
? Windows XP、Windows 7 或 Mac OS X;
? Internet Explorer 6 及更高版本、Firefox 2 及更高版本、Opera 9 及更高的版本、Chrome、 Safari 2
及更高版本。
完整的示例源代碼可以從 http://www.wrox.com/中下載(下載步驟見“源代碼”一節(jié))①。
排版約定
為了讓讀者更好地理解本書內(nèi)容,同時把握住全書的重點,本書將采用以下排版約定。
這種帶警告圖標的方框樣式,表示與上下文相關(guān)的重要的、需要牢記的內(nèi)容。
這種帶鋼筆圖標的方框樣式,表示與上下文相關(guān)的說明、提示、技巧、竅門和背
景知識。
正文中的樣式說明如下。
(1) 新術(shù)語及重要的詞匯在首次出現(xiàn)時使用加粗字體以示強調(diào);
(2) 表示鍵盤命令組合的方式是 Ctrl+A;
(3) 正文中的代碼使用等寬字體,如 persistence.properties;
(4) 代碼有兩種樣式:
var obj = new Object(); // 大多數(shù)示例代碼都沒有加粗
var obj = new Object(); // 加粗的代碼表示在上下文中特別重要
源代碼
在學習本書示例代碼時,可以手工敲入所有代碼,也可以使用隨書的源代碼文件。本書所有源代碼
都可以到 www.wrox.com 中下載。登錄該站點后,先找到本書(通過搜索或者圖書列表),打開本書頁
——————————
① 讀者也可以在圖靈社區(qū)(http://www.ituring.com.cn/)本書的頁面中免費注冊下載。
圖靈社區(qū)會員 StinkBC(StinkBC@gmail.com) 專享 尊重版權(quán)
前 言 5
1
2
3
4
5
13
6
7
8
9
10
11
12
面后,單擊其中的 Download Code 鏈接,就可以下載本書的源代碼了①。對于包含在下載文件中的源代
碼,書中會添加以下圖標:
本書代碼示例旁邊會附有文件名,從中可以找到對應的代碼片段。文件名的格式如下:
代碼片段所在的文件名
由于很多書的書名看起來類似,所以更好的方式是通過書的 ISBN 來搜索它。本
書原版的 ISBN 是 978-1-118-02669-4。
下載完代碼后,請使用解壓縮軟件將其解壓縮。此外,讀者也可以登錄 Wrox 代碼下載主頁
www.wrox.com/dynamic/books/download.aspx,查找并下載本書及其他 Wrox 圖書的示例代碼。
勘誤信息②
我們盡最大努力確保正文和代碼沒有錯誤。可是,金無足赤,錯誤在所難免。如果讀者發(fā)現(xiàn)我們書
中的任何錯誤,例如錯別字或代碼片段無法運行等,希望您能及時給我們反饋。您提交的勘誤不僅能讓
其他讀者受益,而且也能幫助我們進一步提高圖書質(zhì)量。
本書原版的勘誤頁面位于 www.wrox.com 中,登錄該站點后可以通過搜索或查詢圖書列表找到本
書頁面,然后單擊頁面中的 Errata(勘誤)鏈接。然后可以看到其他讀者已經(jīng)提交并由 Wrox 的編輯發(fā)
布的勘誤信息。另外,在 www.wrox.com/misc-pages/booklist.shtml 頁面中也可以找到本書及勘誤頁面
的鏈接。
如果讀者在本書勘誤頁面中沒有發(fā)現(xiàn)“你的”錯誤,麻煩打開 www.wrox.com/contact/techsupport.shtml
頁面,填寫其中的表單并將錯誤發(fā)送給我們。我們會認真核對您提交的錯誤,如果錯誤確實存在,我們
將把它補充到本書勘誤頁面中。同時,也將根據(jù)您提供的信息對本書后續(xù)版本加以改正。
p2p.wrox.com
如果您想與本書作者或者其他讀者溝通,請加入 P2P 論壇(p2p.wrox.com)。該論壇是基于 Web 的
系統(tǒng),您可以在其中發(fā)表與 Wrox 圖書及相關(guān)技術(shù)有關(guān)的帖子,并同其他讀者或者技術(shù)用戶交流。論壇
提供了一個訂閱功能,您可以選擇當發(fā)表您感興趣的帖子時通過郵件通知您。Wrox 的作者、編輯、其
他行業(yè)的專家以及與您正在讀同一本書的讀者都會出現(xiàn)在這個論壇中。
在 http://p2p.wrox.com 中,有很多論壇不僅對您理解本書有幫助,而且還會對開發(fā)應用程序有幫助。
要加入這個論壇,請按下面幾個步驟進行:
(1) 登錄到 p2p.wrox.com,單擊 Register(注冊)鏈接;
——————————
① 翻譯本書時,wrox.com 中下載本書代碼的短地址為:http://tinyurl.com/projs-3rd-code。
② 您也可以登錄圖靈社區(qū)(http://www.ituring.com.cn/),在本書頁面中提交您發(fā)現(xiàn)的錯誤。
圖靈社區(qū)會員 StinkBC(StinkBC@gmail.com) 專享 尊重版權(quán)
6 前 言
(2) 閱讀使用條款并單擊 Agree(同意);
(3) 完成必填信息和您愿意提供的可選信息,然后單擊 Submit(提交);
(4) 隨后,您會收到一封電子郵件,其中包含如何驗證賬號和完成注冊過程的信息。
如果不加入 P2P 論壇,雖然也可以閱讀其中的帖子,但卻不能發(fā)表帖子,只有注
冊后才能發(fā)表。
在加入論壇后,既可以發(fā)表新帖子也可以回復其他用戶的帖子??梢栽谌魏螘r間上網(wǎng)瀏覽論壇中的
帖子。如果希望將某個論壇中的新帖子通過電子郵件發(fā)送給您,請在論壇列表中單擊與論壇名相關(guān)的
Subscribe to this Forum(訂閱這個論壇)圖標。
如果想了解有關(guān)如何使用 Wrox P2P 的更多信息,請閱讀包含論壇規(guī)則、P2P 及 Wrox 圖書常見問題
的 P2P FAQ;要閱讀 FAQ,可以在任何 P2P 頁面中單擊 FAQ 鏈接。
致謝
雖然作者的名字被印在了封面上,但一個人是不可能完成這本書的,我想感謝與出版本書有關(guān)的一
些人。
首先,感謝 John Wiley & Sons 繼續(xù)給我寫作的機會。當時,出版本書第 1 版時,他們是唯一愿意承
擔風險的一家出版社。對此,我將永遠銘記于心。
感謝 John Wiley & Sons 的編輯人員,特別是 Kevin Kent 和 John Peloquin,他們卓有成效的工作使我
保持了坦誠直率的風格,也解決了我在寫作期間不斷變更內(nèi)容的問題。
還要感謝對本書草稿給出反饋意見的所有人:Rob Friesel、Sergey Ilinsky、Dan Kielp、Peter-Paul Koch、
Jeremy McPeak、Alex Petrescu、Dmitry Soshnikov 和 Juriy “Kangax” Zaytsev。你們的寶貴意見讓我自
己都為本書感到驕傲。
我想特別感謝 Brendan Eich,感謝他糾正了第 1 章中有關(guān) JavaScript 歷史的細節(jié)問題。
最后,當然也是非常重要的,感謝 Rey Bango 為本書作序。很高興在與 Rey 通過網(wǎng)絡認識幾年之后,
終于在 2010 年有緣相見。他是這個行業(yè)里真正出色的人,我非常榮幸能請到他為本書作序。
關(guān)于技術(shù)編輯
John Peloquin 是一位有十多年 JavaScript 經(jīng)驗的前端工程師,開發(fā)過各種規(guī)模的應用。John 擁有加
州大學伯克利分校的數(shù)學學士學位,目前在一家致力于衛(wèi)生保健的創(chuàng)業(yè)公司擔任開發(fā)主管。在編輯本書
之前,John 編輯過 Jeremy McPeak 的 JavaScript 24-Hour Trainer(Wiley,2010)。編寫代碼和收集勘誤
之余,John 經(jīng)常沉迷于數(shù)學、哲學和魔術(shù)。
圖靈社區(qū)會員 StinkBC(StinkBC@gmail.com) 專享 尊重版權(quán)
目 錄 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
18
17
目 錄
第 1 章 JavaScript 簡介 .................................1
1.1 JavaScript 簡史 ..........................................1
1.2 JavaScript 實現(xiàn) ..........................................2
1.2.1 ECMAScript...................................3
1.2.2 文檔對象模型(DOM)................5
1.2.3 瀏覽器對象模型(BOM) ............8
1.3 JavaScript 版本 ..........................................8
1.4 小結(jié) ...........................................................9
第 2 章 在 HTML 中使用 JavaScript .........10
2.1 <script>元素........................................10
2.1.1 標簽的位置 ..................................12
2.1.2 延遲腳本 ......................................13
2.1.3 異步腳本 ......................................13
2.1.4 在 XHTML 中的用法...................14
2.1.5 不推薦使用的語法.......................16
2.2 嵌入代碼與外部文件...............................16
2.3 文檔模式..................................................16
2.4 <noscript>元素 ...................................18
2.5 小結(jié) .........................................................18
第 3 章 基本概念............................................19
3.1 語法 .........................................................19
3.1.1 區(qū)分大小寫 ..................................19
3.1.2 標識符..........................................19
3.1.3 注釋..............................................20
3.1.4 嚴格模式 ......................................20
3.1.5 語句..............................................20
3.2 關(guān)鍵字和保留字 ......................................21
3.3 變量 .........................................................22
3.4 數(shù)據(jù)類型..................................................23
3.4.1 typeof 操作符............................23
3.4.2 Undefined 類型 .........................24
3.4.3 Null 類型....................................25
3.4.4 Boolean 類型..............................26
3.4.5 Number 類型................................27
3.4.6 String 類型................................32
3.4.7 Object 類型................................35
3.5 操作符 .....................................................36
3.5.1 一元操作符 ..................................36
3.5.2 位操作符......................................39
3.5.3 布爾操作符 ..................................44
3.5.4 乘性操作符 ..................................47
3.5.5 加性操作符 ..................................48
3.5.6 關(guān)系操作符 ..................................50
3.5.7 相等操作符 ..................................51
3.5.8 條件操作符 ..................................53
3.5.9 賦值操作符 ..................................53
3.5.10 逗號操作符 ................................54
3.6 語句 .........................................................54
3.6.1 if 語句 ........................................54
3.6.2 do-while 語句...........................55
3.6.3 while 語句 .................................55
3.6.4 for 語句......................................56
3.6.5 for-in 語句 ...............................57
3.6.6 label 語句 .................................58
3.6.7 break 和 continue 語句 ..........58
3.6.8 with 語句....................................60
3.6.9 switch 語句 ...............................60
3.7 函數(shù) .........................................................62
3.7.1 理解參數(shù)......................................64
3.7.2 沒有重載......................................66
3.8 小結(jié) .........................................................67
圖靈社區(qū)會員 StinkBC(StinkBC@gmail.com) 專享 尊重版權(quán)
2 目 錄
第 4 章 變量、作用域和內(nèi)存問題..............68
4.1 基本類型和引用類型的值.......................68
4.1.1 動態(tài)的屬性..................................68
4.1.2 復制變量值..................................69
4.1.3 傳遞參數(shù)......................................70
4.1.4 檢測類型......................................72
4.2 執(zhí)行環(huán)境及作用域 ..................................73
4.2.1 延長作用域鏈 ..............................75
4.2.2 沒有塊級作用域 ..........................76
4.3 垃圾收集 .................................................78
4.3.1 標記清除......................................78
4.3.2 引用計數(shù)......................................79
4.3.3 性能問題......................................80
4.3.4 管理內(nèi)存......................................81
4.4 小結(jié) .........................................................81
第 5 章 引用類型............................................83
5.1 Object 類型...........................................83
5.2 Array 類型 .............................................86
5.2.1 檢測數(shù)組......................................88
5.2.2 轉(zhuǎn)換方法......................................89
5.2.3 棧方法..........................................90
5.2.4 隊列方法......................................91
5.2.5 重排序方法..................................92
5.2.6 操作方法......................................94
5.2.7 位置方法......................................95
5.2.8 迭代方法......................................96
5.2.9 歸并方法......................................97
5.3 Date 類型 ...............................................98
5.3.1 繼承的方法................................100
5.3.2 日期格式化方法 ........................101
5.3.3 日期/時間組件方法 ...................102
5.4 RegExp 類型 .........................................103
5.4.1 RegExp 實例屬性......................105
5.4.2 RegExp 實例方法......................106
5.4.3 RegExp 構(gòu)造函數(shù)屬性..............107
5.4.4 模式的局限性 ............................109
5.5 Function 類型.....................................110
5.5.1 沒有重載(深入理解).............111
5.5.2 函數(shù)聲明與函數(shù)表達式.............111
5.5.3 作為值的函數(shù)............................ 112
5.5.4 函數(shù)內(nèi)部屬性............................ 113
5.5.5 函數(shù)屬性和方法 ........................ 116
5.6 基本包裝類型........................................ 118
5.6.1 Boolean 類型........................... 120
5.6.2 Number 類型............................. 120
5.6.3 String 類型............................. 122
5.7 單體內(nèi)置對象........................................ 130
5.7.1 Global 對象............................. 131
5.7.2 Math 對象 ................................. 134
5.8 小結(jié)....................................................... 137
第 6 章 面向?qū)ο蟮某绦蛟O計 .................... 138
6.1 理解對象 ............................................... 138
6.1.1 屬性類型.................................... 139
6.1.2 定義多個屬性............................ 142
6.1.3 讀取屬性的特性 ........................ 143
6.2 創(chuàng)建對象 ............................................... 144
6.2.1 工廠模式.................................... 144
6.2.2 構(gòu)造函數(shù)模式............................ 144
6.2.3 原型模式.................................... 147
6.2.4 組合使用構(gòu)造函數(shù)模式和原型
模式 ........................................... 159
6.2.5 動態(tài)原型模式............................ 159
6.2.6 寄生構(gòu)造函數(shù)模式 .................... 160
6.2.7 穩(wěn)妥構(gòu)造函數(shù)模式 .................... 161
6.3 繼承....................................................... 162
6.3.1 原型鏈 ....................................... 162
6.3.2 借用構(gòu)造函數(shù)............................ 167
6.3.3 組合繼承.................................... 168
6.3.4 原型式繼承................................ 169
6.3.5 寄生式繼承................................ 171
6.3.6 寄生組合式繼承 ........................ 172
6.4 小結(jié)....................................................... 174
第 7 章 函數(shù)表達式 ..................................... 175
7.1 遞歸....................................................... 177
7.2 閉包....................................................... 178
7.2.1 閉包與變量................................ 181
7.2.2 關(guān)于 this 對象......................... 182
7.2.3 內(nèi)存泄漏.................................... 183
圖靈社區(qū)會員 StinkBC(StinkBC@gmail.com) 專享 尊重版權(quán)
目 錄 3
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
18
17
7.3 模仿塊級作用域 ....................................184
7.4 私有變量................................................186
7.4.1 靜態(tài)私有變量 ............................188
7.4.2 模塊模式 ....................................189
7.4.3 增強的模塊模式.........................191
7.5 小結(jié) .......................................................192
第 8 章 BOM .................................................193
8.1 window 對象 .........................................193
8.1.1 全局作用域 ................................193
8.1.2 窗口關(guān)系及框架.........................194
8.1.3 窗口位置 ....................................197
8.1.4 窗口大小 ....................................198
8.1.5 導航和打開窗口.........................199
8.1.6 間歇調(diào)用和超時調(diào)用.................203
8.1.7 系統(tǒng)對話框 ................................205
8.2 location 對象.....................................207
8.2.1 查詢字符串參數(shù).........................207
8.2.2 位置操作 ....................................208
8.3 navigator 對象...................................210
8.3.1 檢測插件 ....................................211
8.3.2 注冊處理程序 ............................213
8.4 screen 對象 .........................................214
8.5 history 對象.......................................215
8.6 小結(jié) .......................................................216
第 9 章 客戶端檢測......................................217
9.1 能力檢測................................................217
9.1.1 更可靠的能力檢測.....................218
9.1.2 能力檢測,不是瀏覽器檢測......220
9.2 怪癖檢測................................................220
9.3 用戶代理檢測 ........................................221
9.3.1 用戶代理字符串的歷史 .............222
9.3.2 用戶代理字符串檢測技術(shù) .........228
9.3.3 完整的代碼 ................................242
9.3.4 使用方法 ....................................245
9.4 小結(jié) .......................................................246
第 10 章 DOM...............................................247
10.1 節(jié)點層次..............................................247
10.1.1 Node 類型..............................248
10.1.2 Document 類型.....................253
10.1.3 Element 類型 .......................261
10.1.4 Text 類型..............................270
10.1.5 Comment 類型 .......................273
10.1.6 CDATASection 類型 ............274
10.1.7 DocumentType 類型 ............274
10.1.8 DocumentFragment 類型....275
10.1.9 Attr 類型..............................276
10.2 DOM 操作技術(shù)....................................277
10.2.1 動態(tài)腳本................................277
10.2.2 動態(tài)樣式................................279
10.2.3 操作表格................................281
10.2.4 使用 NodeList .....................283
10.3 小結(jié) .....................................................284
第 11 章 DOM 擴展 .....................................286
11.1 選擇符 API ..........................................286
11.1.1 querySelector()方法.......286
11.1.2 querySelectorAll()
方法........................................287
11.1.3 matchesSelector()
方法........................................288
11.2 元素遍歷..............................................288
11.3 HTML5 ................................................289
11.3.1 與類相關(guān)的擴充.....................289
11.3.2 焦點管理................................291
11.3.3 HTMLDocument 的變化 ........292
11.3.4 字符集屬性 ............................293
11.3.5 自定義數(shù)據(jù)屬性.....................293
11.3.6 插入標記................................294
11.3.7 scrollIntoView()方法.....298
11.4 專有擴展..............................................298
11.4.1 文檔模式................................298
11.4.2 children 屬性.....................299
11.4.3 contains()方法..................300
11.4.4 插入文本................................301
11.4.5 滾動........................................303
11.5 小結(jié) .....................................................304
圖靈社區(qū)會員 StinkBC(StinkBC@gmail.com) 專享 尊重版權(quán)
4 目 錄
第 12 章 DOM2 和 DOM3 .........................305
12.1 DOM 變化 ...........................................305
12.1.1 針對 XML 命名空間的變化....306
12.1.2 其他方面的變化.....................309
12.2 樣式 .....................................................312
12.2.1 訪問元素的樣式.....................313
12.2.2 操作樣式表 ............................317
12.2.3 元素大小................................320
12.3 遍歷 .....................................................326
12.3.1 NodeIterator.....................328
12.3.2 TreeWalker .........................330
12.4 范圍 .....................................................332
12.4.1 DOM 中的范圍 ......................332
12.4.2 IE8 及更早版本中的范圍.......340
12.5 小結(jié) .....................................................343
第 13 章 事件................................................345
13.1 事件流 .................................................345
13.1.1 事件冒泡................................346
13.1.2 事件捕獲................................346
13.1.3 DOM 事件流 ..........................347
13.2 事件處理程序......................................348
13.2.1 HTML 事件處理程序.............348
13.2.2 DOM0 級事件處理程序.........350
13.2.3 DOM2 級事件處理程序.........351
13.2.4 IE 事件處理程序....................352
13.2.5 跨瀏覽器的事件處理程序 .....353
13.3 事件對象..............................................355
13.3.1 DOM 中的事件對象...............355
13.3.2 IE 中的事件對象....................358
13.3.3 跨瀏覽器的事件對象.............360
13.4 事件類型..............................................362
13.4.1 UI 事件...................................362
13.4.2 焦點事件................................367
13.4.3 鼠標與滾輪事件.....................368
13.4.4 鍵盤與文本事件.....................379
13.4.5 復合事件................................384
13.4.6 變動事件................................385
13.4.7 HTML5 事件..........................388
13.4.8 設備事件................................395
13.4.9 觸摸與手勢事件 .................... 399
13.5 內(nèi)存和性能.......................................... 402
13.5.1 事件委托................................ 402
13.5.2 移除事件處理程序 ................ 404
13.6 模擬事件 ............................................. 405
13.6.1 DOM 中的事件模擬 .............. 405
13.6.2 IE 中的事件模擬.................... 410
13.7 小結(jié)..................................................... 411
第 14 章 表單腳本....................................... 412
14.1 表單的基礎知識.................................. 412
14.1.1 提交表單................................ 413
14.1.2 重置表單................................ 414
14.1.3 表單字段................................ 414
14.2 文本框腳本.......................................... 419
14.2.1 選擇文本................................ 420
14.2.2 過濾輸入................................ 423
14.2.3 自動切換焦點 ........................ 426
14.2.4 HTML5 約束驗證 API........... 427
14.3 選擇框腳本.......................................... 431
14.3.1 選擇選項................................ 432
14.3.2 添加選項................................ 434
14.3.3 移除選項................................ 435
14.3.4 移動和重排選項 .................... 435
14.4 表單序列化.......................................... 436
14.5 富文本編輯.......................................... 438
14.5.1 使用 contenteditable
屬性 ....................................... 438
14.5.2 操作富文本............................ 439
14.5.3 富文本選區(qū)............................ 441
14.5.4 表單與富文本 ........................ 443
14.6 小結(jié)..................................................... 443
第 15 章 使用 Canvas 繪圖....................... 445
15.1 基本用法 ............................................. 445
15.2 2D 上下文............................................ 446
15.2.1 填充和描邊............................ 446
15.2.2 繪制矩形................................ 447
15.2.3 繪制路徑................................ 449
15.2.4 繪制文本................................ 451
15.2.5 變換 ....................................... 453
圖靈社區(qū)會員 StinkBC(StinkBC@gmail.com) 專享 尊重版權(quán)
目 錄 5
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
18
17
15.2.6 繪制圖像 ................................456
15.2.7 陰影........................................457
15.2.8 漸變........................................458
15.2.9 模式........................................460
15.2.10 使用圖像數(shù)據(jù).......................460
15.2.11 合成......................................462
15.3 WebGL.................................................463
15.3.1 類型化數(shù)組 ............................463
15.3.2 WebGL 上下文.......................468
15.3.3 支持........................................478
15.4 小結(jié) .....................................................478
第 16 章 HTML5 腳本編程.........................480
16.1 跨文檔消息傳遞 ..................................480
16.2 原生拖放..............................................481
16.2.1 拖放事件 ................................482
16.2.2 自定義放置目標.....................482
16.2.3 dataTransfer 對象 ............483
16.2.4 dropEffect 與
effectAllowed ...................484
16.2.5 可拖動 ....................................485
16.2.6 其他成員 ................................485
16.3 媒體元素..............................................486
16.3.1 屬性........................................487
16.3.2 事件........................................488
16.3.3 自定義媒體播放器.................488
16.3.4 檢測編解碼器的支持情況......489
16.3.5 Audio 類型............................490
16.4 歷史狀態(tài)管理 ......................................491
16.5 小結(jié) .....................................................492
第 17 章 錯誤處理與調(diào)試...........................493
17.1 瀏覽器報告的錯誤...............................493
17.1.1 IE............................................493
17.1.2 Firefox ....................................494
17.1.3 Safari ......................................496
17.1.4 Opera ......................................497
17.1.5 Chrome ...................................498
17.2 錯誤處理..............................................499
17.2.1 try-catch 語句 ...................500
17.2.2 拋出錯誤 ................................503
17.2.3 錯誤(error)事件 .............505
17.2.4 處理錯誤的策略.....................506
17.2.5 常見的錯誤類型.....................507
17.2.6 區(qū)分致命錯誤和非致命
錯誤........................................510
17.2.7 把錯誤記錄到服務器.............511
17.3 調(diào)試技術(shù)..............................................512
17.3.1 將消息記錄到控制臺.............512
17.3.2 將消息記錄到當前頁面 .........515
17.3.3 拋出錯誤................................515
17.4 常見的 IE 錯誤 ....................................516
17.4.1 操作終止................................516
17.4.2 無效字符................................518
17.4.3 未找到成員 ............................518
17.4.4 未知運行時錯誤.....................519
17.4.5 語法錯誤................................519
17.4.6 系統(tǒng)無法找到指定資源 .........519
17.5 小結(jié) .....................................................520
第 18 章 JavaScript 與 XML .....................521
18.1 瀏覽器對 XML DOM 的支持..............521
18.1.1 DOM2 級核心 ........................521
18.1.2 DOMParser 類型...................522
18.1.3 XMLSerializer 類型 ..........523
18.1.4 IE8 及之前版本中的 XML.....523
18.1.5 跨瀏覽器處理 XML...............527
18.2 瀏覽器對 XPath 的支持.......................529
18.2.1 DOM3 級 XPath .....................529
18.2.2 IE 中的 XPath.........................534
18.2.3 跨瀏覽器使用 XPath..............535
18.3 瀏覽器對 XSLT 的支持.......................537
18.3.1 IE 中的 XSLT.........................537
18.3.2 XSLTProcessor 類型 ..........541
18.3.3 跨瀏覽器使用 XSLT..............543
18.4 小結(jié) .....................................................544
第 19 章 E4X ................................................546
19.1 E4X 的類型..........................................546
19.1.1 XML 類型................................546
19.1.2 XMLList 類型 .......................547
19.1.3 Namespace 類型....................548
圖靈社區(qū)會員 StinkBC(StinkBC@gmail.com) 專享 尊重版權(quán)
6 目 錄
19.1.4 QName 類型............................549
19.2 一般用法..............................................550
19.2.1 訪問特性................................551
19.2.2 其他節(jié)點類型 ........................552
19.2.3 查詢........................................553
19.2.4 構(gòu)建和操作 XML...................555
19.2.5 解析和序列化 ........................557
19.2.6 命名空間................................558
19.3 其他變化..............................................559
19.4 全面啟用 E4X......................................560
19.5 小結(jié) .....................................................561
第 20 章 JSON.............................................562
20.1 語法 .....................................................562
20.1.1 簡單值....................................562
20.1.2 對象........................................563
20.1.3 數(shù)組........................................564
20.2 解析與序列化......................................565
20.2.1 JSON 對象..............................565
20.2.2 序列化選項 ............................566
20.2.3 解析選項................................569
20.3 小結(jié) .....................................................570
第 21 章 Ajax 與 Comet.............................571
21.1 XMLHttpRequest 對象 .....................571
21.1.1 XHR 的用法 ............................573
21.1.2 HTTP 頭部信息......................575
21.1.3 GET 請求................................576
21.1.4 POST 請求..............................577
21.2 XMLHttpRequest 2 級 .........................578
21.2.1 FormData..............................578
21.2.2 超時設定................................579
21.2.3 overrideMimeType()
方法........................................580
21.3 進度事件..............................................580
21.3.1 load 事件..............................580
21.3.2 progress 事件.....................581
21.4 跨源資源共享......................................582
21.4.1 IE 對 CORS 的實現(xiàn)................582
21.4.2 其他瀏覽器對 CORS 的
實現(xiàn)........................................584
21.4.3 Preflighted Reqeusts............... 584
21.4.4 帶憑據(jù)的請求 ........................ 585
21.4.5 跨瀏覽器的 CORS................. 585
21.5 其他跨域技術(shù)...................................... 586
21.5.1 圖像 Ping ............................... 586
21.5.2 JSONP.................................... 587
21.5.3 Comet..................................... 588
21.5.4 服務器發(fā)送事件 .................... 590
21.5.5 Web Sockets........................... 591
21.5.6 SSE 與 Web Sockets .............. 593
21.6 安全..................................................... 593
21.7 小結(jié)..................................................... 594
第 22 章 高級技巧....................................... 596
22.1 高級函數(shù) ............................................. 596
22.1.1 安全的類型檢測 .................... 596
22.1.2 作用域安全的構(gòu)造函數(shù)......... 597
22.1.3 惰性載入函數(shù) ........................ 600
22.1.4 函數(shù)綁定................................ 602
22.1.5 函數(shù)柯里化............................ 604
22.2 防篡改對象.......................................... 606
22.2.1 不可擴展對象 ........................ 606
22.2.2 密封的對象............................ 607
22.2.3 凍結(jié)的對象............................ 608
22.3 高級定時器.......................................... 609
22.3.1 重復的定時器 ........................ 610
22.3.2 Yielding Processes................. 612
22.3.3 函數(shù)節(jié)流................................ 614
22.4 自定義事件.......................................... 616
22.5 拖放..................................................... 618
22.5.1 修繕拖動功能 ........................ 620
22.5.2 添加自定義事件 .................... 622
22.6 小結(jié)..................................................... 624
第 23 章 離線應用與客戶端存儲.............. 626
23.1 離線檢測 ............................................. 626
23.2 應用緩存 ............................................. 627
23.3 數(shù)據(jù)存儲 ............................................. 628
23.3.1 Cookie.................................... 629
23.3.2 IE 用戶數(shù)據(jù) ........................... 637
圖靈社區(qū)會員 StinkBC(StinkBC@gmail.com) 專享 尊重版權(quán)
目 錄 7
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
18
17
23.3.3 Web 存儲機制 ........................638
23.3.4 IndexedDB..............................643
23.4 小結(jié) .....................................................654
第 24 章 最佳實踐........................................656
24.1 可維護性..............................................656
24.1.1 什么是可維護的代碼 .............656
24.1.2 代碼約定 ................................657
24.1.3 松散耦合 ................................659
24.1.4 編程實踐 ................................662
24.2 性能 .....................................................666
24.2.1 注意作用域 ............................666
24.2.2 選擇正確方法.........................667
24.2.3 最小化語句數(shù).........................672
24.2.4 優(yōu)化 DOM 交互......................673
24.3 部署 .....................................................676
24.3.1 構(gòu)建過程 ................................676
24.3.2 驗證........................................677
24.3.3 壓縮........................................679
24.4 小結(jié) .....................................................681
第 25 章 新興的 API....................................682
25.1 requestAnimationFrame()...........682
25.1.1 早期動畫循環(huán).........................682
25.1.2 循環(huán)間隔的問題.....................683
25.1.3 mozRequestAnimationFrame.....................................683
25.1.4 webkitRequestAnimationFrame 與 msRequestAnimationFrame.................685
25.2 Page Visibility API ..............................686
25.3 Geolocation API...................................687
25.4 File API................................................689
25.4.1 FileReader 類型.................690
25.4.2 讀取部分內(nèi)容 ........................692
25.4.3 對象 URL ...............................693
25.4.4 讀取拖放的文件.....................694
25.4.5 使用 XHR 上傳文件...............695
25.5 Web 計時 .............................................696
25.6 Web Workers .......................................697
25.6.1 使用 Worker...........................697
25.6.2 Worker 全局作用域................698
25.6.3 包含其他腳本 ........................699
25.6.4 Web Workers 的未來 .............700
25.7 小結(jié) .....................................................700
附錄 A ECMAScript Harmony .................701
附錄 B 嚴格模式 ..........................................717
附錄 C JavaScript 庫..................................723
附錄 D JavaScript 工具 .............................727
圖靈社區(qū)會員 StinkBC(StinkBC@gmail.com) 專享 尊重版權(quán)
1.1 JavaScript 簡史 1
1
2
3
4
5
13
6
7
8
9
10
11
12
JavaScript 簡介
本章內(nèi)容
? JavaScript 歷史回顧
? JavaScript 是什么
? JavaScript 與 ECMAScript 的關(guān)系
? JavaScript 的不同版本
avaScript 誕生于 1995 年。當時,它的主要目的是處理以前由服務器端語言(如 Perl)負責的一
些輸入驗證操作。在 JavaScript 問世之前,必須把表單數(shù)據(jù)發(fā)送到服務器端才能確定用戶是否
沒有填寫某個必填域,是否輸入了無效的值。Netscape Navigator 希望通過 JavaScript 來解決這個問題。
在人們普遍使用電話拔號上網(wǎng)的年代,能夠在客戶端完成一些基本的驗證任務絕對是令人興奮的。畢竟,
撥號上網(wǎng)的速度之慢,導致了與服務器的每一次數(shù)據(jù)交換事實上都成了對人們耐心的一次考驗。
自此以后,JavaScript 逐漸成為市面上常見瀏覽器必備的一項特色功能。如今,JavaScript 的用途早
已不再局限于簡單的數(shù)據(jù)驗證,而是具備了與瀏覽器窗口及其內(nèi)容等幾乎所有方面交互的能力。今天的
JavaScript 已經(jīng)成為一門功能全面的編程語言,能夠處理復雜的計算和交互,擁有了閉包、匿名(lamda,
拉姆達)函數(shù),甚至元編程等特性。作為 Web 的一個重要組成部分,JavaScript 的重要性是不言而喻的,
就連手機瀏覽器,甚至那些專為殘障人士設計的瀏覽器等非常規(guī)瀏覽器都支持它。當然,微軟的例子更
為典型。雖然有自己的客戶端腳本語言 VBScript,但微軟仍然在 Internet Explorer 的早期版本中加入了
自己的 JavaScript 實現(xiàn)①。
JavaScript 從一個簡單的輸入驗證器發(fā)展成為一門強大的編程語言,完全出乎人們的意料。應該說,
它既是一門非常簡單的語言,又是一門非常復雜的語言。說它簡單,是因為學會使用它只需片刻功夫;
而說它復雜,是因為要真正掌握它則需要數(shù)年時間。要想全面理解和掌握 JavaScript,關(guān)鍵在于弄清楚
它的本質(zhì)、歷史和局限性。
1.1 JavaScript 簡史
在 Web 日益流行的同時,人們對客戶端腳本語言的需求也越來越強烈。那個時候,絕大多數(shù)因
特網(wǎng)用戶都使用速度僅為 28.8kbit/s 的“貓”(調(diào)制解調(diào)器)上網(wǎng),但網(wǎng)頁的大小和復雜性卻不斷增
加。為完成簡單的表單驗證而頻繁地與服務器交換數(shù)據(jù)只會加重用戶的負擔。想象一下:用戶填寫
完一個表單,單擊“提交”按鈕,然后等待 30 秒鐘,最終服務器返回消息說有一個必填字段沒有
——————————
① 對 IE 而言,當我們提到 JavaScript 時,實際上就是指 IE 對 JavaScript(ECMAScript)的實現(xiàn)——JScript。最早的 JScript
基于 Netscape JavaScript 1.0 開發(fā),于 1996 年 8 月隨同 Internet Explorer 3.0 發(fā)布。
J
第 1 章
圖靈社區(qū)會員 StinkBC(StinkBC@gmail.com) 專享 尊重版權(quán)
2 第 1 章 JavaScript 簡介
填好……當時走在技術(shù)革新最前沿的 Netscape 公司,決定著手開發(fā)一種客戶端語言,用來處理這種
簡單的驗證。
當時就職于 Netscape 公司的布蘭登·艾奇(Brendan Eich),開始著手為計劃于 1995 年 2 月發(fā)布的
Netscape Navigator 2 開發(fā)一種名為 LiveScript 的腳本語言——該語言將同時在瀏覽器和服務器中使用
(它在服務器上的名字叫 LiveWire)。為了趕在發(fā)布日期前完成 LiveScript 的開發(fā),Netscape 與 Sun 公司
建立了一個開發(fā)聯(lián)盟。在 Netscape Navigator 2 正式發(fā)布前夕,Netscape 為了搭上媒體熱炒 Java 的順風車,
臨時把 LiveScript 改名為 JavaScript。
由于 JavaScript 1.0 獲得了巨大成功,Netscape 隨即在 Netscape Navigator 3 中又發(fā)布了 JavaScript 1.1。
Web 雖然羽翼未豐,但用戶關(guān)注度卻屢創(chuàng)新高。在這樣的背景下,Netscape 把自己定位為市場領袖型公
司。與此同時,微軟決定向與 Navigator 競爭的自家產(chǎn)品 Internet Explorer 瀏覽器投入更多資源。Netscape
Navigator 3 發(fā)布后不久,微軟就在其 Internet Explorer 3 中加入了名為 JScript 的 JavaScript 實現(xiàn)(命名為
JScript 是為了避開與 Netscape 有關(guān)的授權(quán)問題)。以現(xiàn)在的眼光來看,微軟 1996 年 8 月為進入 Web 瀏覽
器領域而實施的這個重大舉措,是導致 Netscape 日后蒙羞的一個標志性事件。然而,這個重大舉措同時
也標志著 JavaScript 作為一門語言,其開發(fā)向前邁進了一大步。
微軟推出其 JavaScript 實現(xiàn)意味著有了兩個不同的 JavaScript 版本:Netscape Navigator 中的
JavaScript、Internet Explorer 中的 JScript。與 C 及其他編程語言不同,當時還沒有標準規(guī)定 JavaScript 的
語法和特性,兩個不同版本并存的局面已經(jīng)完全暴露了這個問題。隨著業(yè)界擔心的日益加劇,JavaScript
的標準化問題被提上了議事日程。
1997 年,以 JavaScript 1.1 為藍本的建議被提交給了歐洲計算機制造商協(xié)會(ECMA,European
Computer Manufacturers Association)。該協(xié)會指定 39 號技術(shù)委員會(TC39,Technical Committee #39)
負責“標準化一種通用、跨平臺、供應商中立的腳本語言的語法和語義”(http://www.ecma
international.org/memento/TC39.htm)。TC39 由來自 Netscape、Sun、微軟、Borland 及其他關(guān)注腳本語言
發(fā)展的公司的程序員組成,他們經(jīng)過數(shù)月的努力完成了 ECMA-262——定義一種名為 ECMAScript(發(fā)
音為“ek-ma-script”)的新腳本語言的標準。
第二年,ISO/IEC(International Organization for Standardization and International Electrotechnical
Commission,國標標準化組織和國際電工委員會)也采用了 ECMAScript 作為標準(即 ISO/IEC-16262)。
自此以后,瀏覽器開發(fā)商就開始致力于將 ECMAScript 作為各自 JavaScript 實現(xiàn)的基礎,也在不同程度
上取得了成功。
1.2 JavaScript 實現(xiàn)
雖然 JavaScript 和 ECMAScript 通常都被人們用來表達
相同的含義,但 JavaScript 的含義卻比 ECMA-262 中規(guī)定的
要多得多。沒錯,一個完整的 JavaScript 實現(xiàn)應該由下列三
個不同的部分組成(見圖 1-1)。
? 核心(ECMAScript)
? 文檔對象模型(DOM)
? 瀏覽器對象模型(BOM) 圖 1-1
圖靈社區(qū)會員 StinkBC(StinkBC@gmail.com) 專享 尊重版權(quán)
1.2 JavaScript 實現(xiàn) 3
1
2
3
4
5
13
6
7
8
9
10
11
12
1.2.1 ECMAScript
由 ECMA-262 定義的 ECMAScript 與 Web 瀏覽器沒有依賴關(guān)系。實際上,這門語言本身并不包含輸
入和輸出定義。ECMA-262 定義的只是這門語言的基礎,而在此基礎之上可以構(gòu)建更完善的腳本語言。
我們常見的 Web 瀏覽器只是 ECMAScript 實現(xiàn)可能的宿主環(huán)境之一。宿主環(huán)境不僅提供基本的
ECMAScript 實現(xiàn),同時也會提供該語言的擴展,以便語言與環(huán)境之間對接交互。而這些擴展——如
DOM,則利用 ECMAScript 的核心類型和語法提供更多更具體的功能,以便實現(xiàn)針對環(huán)境的操作。其他
宿主環(huán)境包括 Node(一種服務端 JavaScript 平臺)和 Adobe Flash。
既然 ECMA-262 標準沒有參照 Web 瀏覽器,那它都規(guī)定了些什么內(nèi)容呢?大致說來,它規(guī)定了這
門語言的下列組成部分:
? 語法
? 類型
? 語句
? 關(guān)鍵字
? 保留字
? 操作符
? 對象
ECMAScript 就是對實現(xiàn)該標準規(guī)定的各個方面內(nèi)容的語言的描述。JavaScript 實現(xiàn)了 ECMAScript,
Adobe ActionScript 同樣也實現(xiàn)了 ECMAScript。
1. ECMAScript 的版本
ECMAScript 的不同版本又稱為版次,以第 x 版表示(意即描述特定實現(xiàn)的 ECMA-262 規(guī)范的第 x
個版本)。ECMA-262 的最近一版是第 5 版,發(fā)布于 2009 年。而 ECMA-262 的第 1 版本質(zhì)上與 Netscape
的 JavaScript 1.1 相同——只不過刪除了所有針對瀏覽器的代碼并作了一些較小的改動:ECMA-262 要求
支持 Unicode 標準(從而支持多語言開發(fā)),而且對象也變成了平臺無關(guān)的(Netscape JavaScript 1.1 的對
象在不同平臺中的實現(xiàn)不一樣,例如 Date 對象)。這也是 JavaScript 1.1 和 1.2 與 ECMA-262 第 1 版不一
致的主要原因。
ECMA-262 第 2 版主要是編輯加工的結(jié)果。這一版中內(nèi)容的更新是為了與 ISO/IEC-16262 保持嚴格
一致,沒有作任何新增、修改或刪節(jié)處理。因此,一般不使用第 2 版來衡量 ECMAScript 實現(xiàn)的兼容性。
ECMA-262 第 3 版才是對該標準第一次真正的修改。修改的內(nèi)容涉及字符串處理、錯誤定義和數(shù)
值輸出。這一版還新增了對正則表達式、新控制語句、try-catch 異常處理的支持,并圍繞標準的
國際化做出了一些小的修改。從各方面綜合來看,第 3 版標志著 ECMAScript 成為了一門真正的編程
語言。
ECMA-262 第 4 版對這門語言進行了一次全面的檢核修訂。由于 JavaScript 在 Web 上日益流行,開
發(fā)人員紛紛建議修訂 ECMAScript,以使其能夠滿足不斷增長的 Web 開發(fā)需求。作為回應,ECMA TC39
重新召集相關(guān)人員共同謀劃這門語言的未來。結(jié)果,出臺后的標準幾乎在第 3 版基礎上完全定義了一門
新語言。第 4 版不僅包含了強類型變量、新語句和新數(shù)據(jù)結(jié)構(gòu)、真正的類和經(jīng)典繼承,還定義了與數(shù)據(jù)
交互的新方式。
與此同時,TC39 下屬的一個小組也提出了一個名為 ECMAScript 3.1 的替代性建議,該建議只對這
門語言進行了較少的改進。這個小組認為第 4 版給這門語言帶來的跨越太大了。因此,該小組建議對這
圖靈社區(qū)會員 StinkBC(StinkBC@gmail.com) 專享 尊重版權(quán)
4 第 1 章 JavaScript 簡介
門語言進行小幅修訂,能夠在現(xiàn)有 JavaScript 引擎基礎上實現(xiàn)。最終,ES3.1 附屬委員會獲得的支持超過
了 TC39,ECMA-262 第 4 版在正式發(fā)布前被放棄。
ECMAScript 3.1 成為 ECMA-262 第 5 版,并于 2009 年 12 月 3 日正式發(fā)布。第 5 版力求澄清第 3
版中已知的歧義并增添了新的功能。新功能包括原生 JSON 對象(用于解析和序列化 JSON 數(shù)據(jù))、繼
承的方法和高級屬性定義,另外還包含一種嚴格模式,對 ECMAScript 引擎解釋和執(zhí)行代碼進行了補充
說明。
2. 什么是 ECMAScript 兼容
ECMA-262 給出了 ECMAScript 兼容的定義。要想成為 ECMAScript 的實現(xiàn),則該實現(xiàn)必須做到:
? 支持 ECMA-262 描述的所有“類型、值、對象、屬性、函數(shù)以及程序句法和語義”(ECMA-262
第 1 頁);
? 支持 Unicode 字符標準。
此外,兼容的實現(xiàn)還可以進行下列擴展。
? 添加 ECMA-262 沒有描述的“更多類型、值、對象、屬性和函數(shù)”。ECMA-262 所說的這些新增
特性,主要是指該標準中沒有規(guī)定的新對象和對象的新屬性。
? 支持 ECMA-262 沒有定義的“程序和正則表達式語法”。(也就是說,可以修改和擴展內(nèi)置的正
則表達式語法。)
上述要求為兼容實現(xiàn)的開發(fā)人員基于 ECMAScript 開發(fā)一門新語言提供了廣闊的空間和極大的靈活
性,這也從另一個側(cè)面說明了 ECMAScript 受開發(fā)人員歡迎的原因。
3. Web 瀏覽器對 ECMAScript 的支持
1996 年,Netscape Navigator 3 捆綁發(fā)布了 JavaScript 1.1。而相同的 JavaScript 1.1 設計規(guī)范隨后作為
對新標準(ECMA-262)的建議被提交給 Ecma。伴隨著 JavaScript 的迅速走紅,Netscape 豪情滿懷地著
手開發(fā) JavaScript 1.2。然而,問題是 Ecma 當時還沒有接受 Netscape 的建議。
Netscape Navigator 3 發(fā)布后不久,微軟也推出了 Internet Explorer 3。微軟在 IE 的這一版中捆綁了
JScript 1.0,很多人都認為 JScript 1.0 與 JavaScript 1.1 應該是一樣的。但是,由于沒有文檔依據(jù),加之不
適當?shù)奶匦阅7?,JScript 1.0 還是很難與 JavaScript 1.1 相提并論。
1997 年,內(nèi)置 JavaScript 1.2 的 Netscape Navigator 4 發(fā)布;而到這一年年底,ECMA-262 第 1 版也
被接受并實現(xiàn)了標準化。結(jié)果,雖然 ECMAScript 被認為是基于 JavaScript 1.1 制定的,但 JavaScript 1.2
與 ECMAScript 的第 1 版并不兼容。
JScript 的升級版是 Internet Explorer 4 中內(nèi)置的 JScript 3.0(隨同微軟 IIS 3.0 發(fā)布的 JScript 2.0 從來
也沒有移植到瀏覽器中)。微軟通過媒體大肆宣傳 JScript 3.0 是世界上第一個 ECMA 兼容的腳本語言,
但當時的 ECMA-262 尚未定稿。于是,JScript 3.0 與 JavaScript 1.2 都遭遇了相同的尷尬局面——誰都沒
有按照最終的 ECMAScript 標準來實現(xiàn)。
Netscape 決定更新其 JavaScript 實現(xiàn),即在 Netscape Navigator 4.06 中發(fā)布 JavaScript 1.3,從而做到
了與 ECMA-262 的第一個版本完全兼容。在 JavaScript 1.3 中,Netscape 增加了對 Unicode 標準的支持,
并在保留 JavaScript 1.2 新增特性的同時實現(xiàn)了所有對象的平臺中立化。
在 Netscape 以 Mozilla 項目的名義開放其源代碼時,預期 JavaScript 1.4 將隨同 Netscape Navigator 5
一道發(fā)布。然而,一個激進的決定,徹底重新設計 Netscape 代碼,打亂了原有計劃。后來,JavaScript 1.4
只發(fā)布了針對 Netscape Enterprise Server 的服務器版,而沒有內(nèi)置于 Web 瀏覽器中。
到了 2008 年,五大主流 Web 瀏覽器(IE、Firefox、Safari、Chrome 和 Opera)全部做到了與 ECMA-262
圖靈社區(qū)會員 StinkBC(StinkBC@gmail.com) 專享 尊重版權(quán)
1.2 JavaScript 實現(xiàn) 5
1
2
3
4
5
13
6
7
8
9
10
11
12
兼容。IE8 是第一個著手實現(xiàn) ECMA-262 第 5 版的瀏覽器,并在 IE9 中提供了完整的支持。Firefox 4 也
緊隨其后做到兼容。下表列出了 ECMAScript 受主流 Web 瀏覽器支持的情況。
瀏 覽 器 ECMAScript兼容性 瀏 覽 器 ECMAScript兼容性
Netscape Navigator 2 — Opera 6~7.1 第2版
Netscape Navigator 3 — Opera 7.2+ 第3版
Netscape Navigator 4~4.05 — Safari 1~2.0.x 第3版*
Netscape Navigator 4.06~4.79 第1版 Safari 3.x 第3版
Netscape 6+(Mozilla 0.6.0+) 第3版 Safari 4.x~5.x 第5版*
IE3 — Chrome 1+ 第3版
IE4 — Firefox 1~2 第3版
IE5 第1版 Firefox 3.0.x 第3版
IE5.5~IE7 第3版 Firefox 3.5~3.6 第5版*
IE8 第5版* Firefox 4.0 + 第5版
IE9+ 第5版
* 不完全兼容的實現(xiàn)
1.2.2 文檔對象模型(DOM)
文檔對象模型(DOM,Document Object Model)是針對 XML 但經(jīng)過擴展用于 HTML 的應用程序編
程接口(API,Application Programming Interface)。DOM 把整個頁面映射為一個多層節(jié)點結(jié)構(gòu)。HTML
或 XML 頁面中的每個組成部分都是某種類型的節(jié)點,這些節(jié)點又包含著不同類型的數(shù)據(jù)??聪旅孢@個
HTML 頁面:
<html>
<head>
<title>Sample Page</title>
</head>
<body>
<p>Hello World!</p>
</body>
</html>
在 DOM 中,這個頁面可以通過圖 1-2 所示的分層節(jié)點圖表示。
通過 DOM 創(chuàng)建的這個表示文檔的樹形圖,開發(fā)人員獲得了控制頁面內(nèi)容和結(jié)構(gòu)的主動權(quán)。借助
DOM 提供的 API,開發(fā)人員可以輕松自如地刪除、添加、替換或修改任何節(jié)點。
1. 為什么要使用 DOM
在 Internet Explorer 4 和 Netscape Navigator 4 分別支持的不同形式的 DHTML(Dynamic HTML)基
礎上,開發(fā)人員首次無需重新加載網(wǎng)頁,就可以修改其外觀和內(nèi)容了。然而,DHTML 在給 Web 技術(shù)發(fā)
展帶來巨大進步的同時,也帶來了巨大的問題。由于 Netscape 和微軟在開發(fā) DHTML 方面各持己見,過
去那個只編寫一個 HTML 頁面就能夠在任何瀏覽器中運行的時代結(jié)束了。
對開發(fā)人員而言,如果想繼續(xù)保持 Web 跨平臺的天性,就必須額外多做一些工作。而人們真正擔
心的是,如果不對 Netscape 和微軟加以控制,Web 開發(fā)領域就會出現(xiàn)技術(shù)上兩強割據(jù),瀏覽器互不兼
圖靈社區(qū)會員 StinkBC(StinkBC@gmail.com) 專享 尊重版權(quán)
6 第 1 章 JavaScript 簡介
容的局面。此時,負責制定 Web 通信標準的 W3C(World Wide Web Consortium,萬維網(wǎng)聯(lián)盟)開始著
手規(guī)劃 DOM。
圖 1-2
2. DOM 級別
DOM1 級(DOM Level 1)于 1998 年 10 月成為 W3C 的推薦標準。DOM1 級由兩個模塊組成:DOM
核心(DOM Core)和 DOM HTML。其中,DOM 核心規(guī)定的是如何映射基于 XML 的文檔結(jié)構(gòu),以便
簡化對文檔中任意部分的訪問和操作。DOM HTML 模塊則在 DOM 核心的基礎上加以擴展,添加了針
對 HTML 的對象和方法。
請讀者注意,DOM 并不只是針對 JavaScript 的,很多別的語言也都實現(xiàn)了 DOM。
不過,在 Web 瀏覽器中,基于 ECMAScript 實現(xiàn)的 DOM 的確已經(jīng)成為 JavaScript 這
門語言的一個重要組成部分。
如果說 DOM1 級的目標主要是映射文檔的結(jié)構(gòu),那么 DOM2 級的目標就要寬泛多了。DOM2 級在
原來 DOM 的基礎上又擴充了(DHTML 一直都支持的)鼠標和用戶界面事件、范圍、遍歷(迭代 DOM
文檔的方法)等細分模塊,而且通過對象接口增加了對 CSS(Cascading Style Sheets,層疊樣式表)的
支持。DOM1 級中的 DOM 核心模塊也經(jīng)過擴展開始支持 XML 命名空間。
DOM2 級引入了下列新模塊,也給出了眾多新類型和新接口的定義。
? DOM 視圖(DOM Views):定義了跟蹤不同文檔(例如,應用 CSS 之前和之后的文檔)視圖的
接口;
? DOM 事件(DOM Events):定義了事件和事件處理的接口;
? DOM 樣式(DOM Style):定義了基于 CSS 為元素應用樣式的接口;
? DOM 遍歷和范圍(DOM Traversal and Range):定義了遍歷和操作文檔樹的接口。
DOM3 級則進一步擴展了 DOM,引入了以統(tǒng)一方式加載和保存文檔的方法——在 DOM 加載和保
存(DOM Load and Save)模塊中定義;新增了驗證文檔的方法——在 DOM 驗證(DOM Validation)模
圖靈社區(qū)會員 StinkBC(StinkBC@gmail.com) 專享 尊重版權(quán)
1.2 JavaScript 實現(xiàn) 7
1
2
3
4
5
13
6
7
8
9
10
11
12
塊中定義。DOM3 級也對 DOM 核心進行了擴展,開始支持 XML 1.0 規(guī)范,涉及 XML Infoset、XPath
和 XML Base。
在閱讀 DOM 標準的時候,讀者可能會看到 DOM0 級(DOM Level 0)的字眼。
實際上,DOM0 級標準是不存在的;所謂 DOM0 級只是 DOM 歷史坐標中的一個參照
點而已。具體說來,DOM0 級指的是 Internet Explorer 4.0 和 Netscape Navigator 4.0 最
初支持的 DHTML。
3. 其他 DOM 標準
除了 DOM 核心和 DOM HTML 接口之外,另外幾種語言還發(fā)布了只針對自己的 DOM 標準。下面
列出的語言都是基于 XML 的,每種語言的 DOM 標準都添加了與特定語言相關(guān)的新方法和新接口:
? SVG(Scalable Vector Graphic,可伸縮矢量圖)1.0;
? MathML(Mathematical Markup Language,數(shù)學標記語言)1.0;
? SMIL(Synchronized Multimedia Integration Language,同步多媒體集成語言)。
還有一些語言也開發(fā)了自己的 DOM 實現(xiàn),例如 Mozilla 的 XUL(XML User Interface Language,XML
用戶界面語言)。但是,只有上面列出的幾種語言是 W3C 的推薦標準。
4. Web 瀏覽器對 DOM 的支持
在 DOM 標準出現(xiàn)了一段時間之后,Web 瀏覽器才開始實現(xiàn)它。微軟在 IE5 中首次嘗試實現(xiàn) DOM,
但直到 IE5.5 才算是真正支持 DOM1 級。在隨后的 IE6 和 IE7 中,微軟都沒有引入新的 DOM 功能,而
到了 IE8 才對以前 DOM 實現(xiàn)中的 bug 進行了修復。
Netscape 直到 Netscape 6(Mozilla 0.6.0)才開始支持 DOM。在 Netscape 7 之后,Mozilla 把開發(fā)重心轉(zhuǎn)
向了 Firefox 瀏覽器。Firefox 3 完全支持 DOM1 級,幾乎完全支持 DOM2 級,甚至還支持 DOM3 級的一部
分。(Mozilla 開發(fā)團隊的目標是構(gòu)建與標準 100%兼容的瀏覽器,而他們的努力也得到了回報。)
目前,支持 DOM 已經(jīng)成為瀏覽器開發(fā)商的首要目標,主流瀏覽器每次發(fā)布新版本都會改進對 DOM
的支持。下表列出了主流瀏覽器對 DOM 標準的支持情況。
瀏 覽 器 DOM兼容性
Netscape Navigator 1. ~ 4.x —
Netscape 6+ (Mozilla 0.6.0+) 1級、2級(幾乎全部)、3級(部分)
IE2~IE4.x —
IE5 1級(最小限度)
IE5.5~IE8 1級(幾乎全部)
IE9+ 1級、2級、3級
Opera 1~6 —
Opera 7~8.x 1級(幾乎全部)、2級(部分)
Opera 9~9.9 1級、2級(幾乎全部)、3級(部分)
Opera 10+ 1級、2級、3級(部分)
Safari 1.0.x 1級
Safari 2+ 1級、2級(部分)
Chrome 1+ 1級、2級(部分)
Firefox 1+ 1級、2級(幾乎全部)、3級(部分)
圖靈社區(qū)會員 StinkBC(StinkBC@gmail.com) 專享 尊重版權(quán)
8 第 1 章 JavaScript 簡介
1.2.3 瀏覽器對象模型(BOM)
Internet Explorer 3 和 Netscape Navigator 3 有一個共同的特色,那就是支持可以訪問和操作瀏覽器窗
口的瀏覽器對象模型(BOM,Browser Object Model)。開發(fā)人員使用 BOM 可以控制瀏覽器顯示的頁面
以外的部分。而 BOM 真正與眾不同的地方(也是經(jīng)常會導致問題的地方),還是它作為 JavaScript 實現(xiàn)
的一部分但卻沒有相關(guān)的標準。這個問題在 HTML5 中得到了解決,HTML5 致力于把很多 BOM 功能寫
入正式規(guī)范。HTML5 發(fā)布后,很多關(guān)于 BOM 的困惑煙消云散。
從根本上講,BOM 只處理瀏覽器窗口和框架;但人們習慣上也把所有針對瀏覽器的 JavaScript 擴展
算作 BOM 的一部分。下面就是一些這樣的擴展:
? 彈出新瀏覽器窗口的功能;
? 移動、縮放和關(guān)閉瀏覽器窗口的功能;
? 提供瀏覽器詳細信息的 navigator 對象;
? 提供瀏覽器所加載頁面的詳細信息的 location 對象;
? 提供用戶顯示器分辨率詳細信息的 screen 對象;
? 對 cookies 的支持;
? 像 XMLHttpRequest 和 IE 的 ActiveXObject 這樣的自定義對象。
由于沒有 BOM 標準可以遵循,因此每個瀏覽器都有自己的實現(xiàn)。雖然也存在一些事實標準,例如
要有 window 對象和 navigator 對象等,但每個瀏覽器都會為這兩個對象乃至其他對象定義自己的屬
性和方法?,F(xiàn)在有了 HTML5,BOM 實現(xiàn)的細節(jié)有望朝著兼容性越來越高的方向發(fā)展。第 8 章將深入討
論 BOM。
1.3 JavaScript 版本
作為 Netscape“繼承人”的 Mozilla 公司,是目前唯一還在沿用最初的 JavaScript 版本編號序列的瀏
覽器開發(fā)商。在 Netscape 將源代碼提交給開源的 Mozilla 項目的時候,JavaScript 在瀏覽器中的最后一個
版本號是 1.3。(如前所述,1.4 版是只針對服務器的實現(xiàn)。)后來,隨著 Mozilla 基金會繼續(xù)開發(fā) JavaScript,
添加新的特性、關(guān)鍵字和語法,JavaScript 的版本號繼續(xù)遞增。下表列出了 Netscape/Mozilla 瀏覽器中
JavaScript 版本號的遞增過程:
瀏 覽 器 JavaScript版本 瀏 覽 器 JavaScript版本
Netscape Navigator 2 1.0 Firefox 1.5 1.6
Netscape Navigator 3 1.1 Firefox 2 1.7
Netscape Navigator 4 1.2 Firefox 3 1.8
Netscape Navigator 4.06 1.3 Firefox 3.5 1.8.1
Netscape 6+(Mozilla 0.6.0+) 1.5 Firefox 3.6 1.8.2
Firefox 1 1.5
實際上,上表中的編號方案源自 Firefox 4 將內(nèi)置 JavaScript 2.0 這一共識。因此,2.0 版之前每個遞
增的版本號,表示的是相應實現(xiàn)與 JavaScript 2.0 開發(fā)目標還有多大的距離。雖然原計劃是這樣,但
JavaScript 的這種發(fā)展速度讓這個計劃不再可行。目前,JavaScript 2.0 還沒有目標實現(xiàn)。
圖靈社區(qū)會員 StinkBC(StinkBC@gmail.com) 專享 尊重版權(quán)
1.4 小結(jié) 9
1
2
3
4
5
13
6
7
8
9
10
11
12
請注意,只有 Netscape/Mozilla 瀏覽器才遵循這種編號模式。例如,IE 的 JScript
就采用了另一種版本命名方案。換句話說,JScript 的版本號與上表中 JavaScript 的版
本號之間不存在任何對應關(guān)系。而且,大多數(shù)瀏覽器在提及對 JavaScript 的支持情況
時,一般都以 ECMAScript 兼容性和對 DOM 的支持情況為準。
1.4 小結(jié)
JavaScript 是一種專為與網(wǎng)頁交互而設計的腳本語言,由下列三個不同的部分組成:
? ECMAScript,由 ECMA-262 定義,提供核心語言功能;
? 文檔對象模型(DOM),提供訪問和操作網(wǎng)頁內(nèi)容的方法和接口;
? 瀏覽器對象模型(BOM),提供與瀏覽器交互的方法和接口。
JavaScript 的這三個組成部分,在當前五個主要瀏覽器(IE、Firefox、Chrome、Safari 和 Opera)中
都得到了不同程度的支持。其中,所有瀏覽器對 ECMAScript 第 3 版的支持大體上都還不錯,而對
ECMAScript 5 的支持程度越來越高,但對 DOM 的支持則彼此相差比較多。對已經(jīng)正式納入 HTML5 標
準的 BOM 來說,盡管各瀏覽器都實現(xiàn)了某些眾所周知的共同特性,但其他特性還是會因瀏覽器而異。
圖靈社區(qū)會員 StinkBC(StinkBC@gmail.com) 專享 尊重版權(quán)
10 第 2 章 在 HTML 中使用 JavaScript
在 HTML 中使用 JavaScript
本章內(nèi)容
? 使用<script>元素
? 嵌入腳本與外部腳本
? 文檔模式對 JavaScript 的影響
? 考慮禁用 JavaScript 的場景
要一提到把 JavaScript 放到網(wǎng)頁中,就不得不涉及 Web 的核心語言——HTML。在當初開發(fā)
JavaScript 的時候,Netscape 要解決的一個重要問題就是如何做到讓 JavaScript 既能與 HTML
頁面共存,又不影響那些頁面在其他瀏覽器中的呈現(xiàn)效果。經(jīng)過嘗試、糾錯和爭論,最終的決定就是
為 Web 增加統(tǒng)一的腳本支持。而 Web 誕生早期的很多做法也都保留了下來,并被正式納入 HTML 規(guī)
范當中。
2.1 <script>元素
向 HTML 頁面中插入 JavaScript 的主要方法,就是使用<script>元素。這個元素由 Netscape 創(chuàng)造
并在 Netscape Navigator 2 中首先實現(xiàn)。后來,這個元素被加入到正式的 HTML 規(guī)范中。HTML 4.01 為
<script>定義了下列 6 個屬性。
? async:可選。表示應該立即下載腳本,但不應妨礙頁面中的其他操作,比如下載其他資源或
等待加載其他腳本。只對外部腳本文件有效。
? charset:可選。表示通過 src 屬性指定的代碼的字符集。由于大多數(shù)瀏覽器會忽略它的值,
因此這個屬性很少有人用。
? defer:可選。表示腳本可以延遲到文檔完全被解析和顯示之后再執(zhí)行。只對外部腳本文件有
效。IE7 及更早版本對嵌入腳本也支持這個屬性。
? language:已廢棄。原來用于表示編寫代碼使用的腳本語言(如 JavaScript、JavaScript1.2
或 VBScript)。大多數(shù)瀏覽器會忽略這個屬性,因此也沒有必要再用了。
? src:可選。表示包含要執(zhí)行代碼的外部文件。
? type:可選??梢钥闯墒?language 的替代屬性;表示編寫代碼使用的腳本語言的內(nèi)容類型(也
稱為 MIME 類型)。雖然 text/javascript 和 text/ecmascript 都已經(jīng)不被推薦使用,但人
們一直以來使用的都還是 text/javascript。實際上,服務器在傳送 JavaScript 文件時使用的
MIME 類型通常是 application/x–javascript,但在 type 中設置這個值卻可能導致腳本被
忽略。另外,在非IE瀏覽器中還可以使用以下值:application/javascript和application/
只
第 2 章
圖靈社區(qū)會員 StinkBC(StinkBC@gmail.com) 專享 尊重版權(quán)
2.1 <script>元素 11
1
2
3
4
5
13
6
7
8
9
10
11
12
ecmascript。考慮到約定俗成和最大限度的瀏覽器兼容性,目前 type 屬性的值依舊還是
text/javascript。不過,這個屬性并不是必需的,如果沒有指定這個屬性,則其默認值仍為
text/javascript。
使用<script>元素的方式有兩種:直接在頁面中嵌入 JavaScript 代碼和包含外部 JavaScript
文件。
在使用<script>元素嵌入 JavaScript 代碼時,只須為<script>指定 type 屬性。然后,像下面這
樣把 JavaScript 代碼直接放在元素內(nèi)部即可:
<script type=\"text/javascript\">
function sayHi(){
alert(\"Hi!\");
}
</script>
包含在<script>元素內(nèi)部的 JavaScript 代碼將被從上至下依次解釋。就拿前面這個例子來說,解釋
器會解釋一個函數(shù)的定義,然后將該定義保存在自己的環(huán)境當中。在解釋器對<script>元素內(nèi)部的所
有代碼求值完畢以前,頁面中的其余內(nèi)容都不會被瀏覽器加載或顯示。
在使用<script>嵌入 JavaScript 代碼時,記住不要在代碼中的任何地方出現(xiàn)\"</script>\"字符串。
例如,瀏覽器在加載下面所示的代碼時就會產(chǎn)生一個錯誤:
<script type=\"text/javascript\">
function sayScript(){
alert(\"</script>\");
}
</script>
因為按照解析嵌入式代碼的規(guī)則,當瀏覽器遇到字符串\"</script>\"時,就會認為那是結(jié)束的
</script>標簽。而通過轉(zhuǎn)義字符“/”可以解決這個問題,例如:
<script type=\"text/javascript\">
function sayScript(){
alert(\"<\\/script>\");
}
</script>
這樣寫代碼瀏覽器可以接受,因而也就不會導致錯誤了。
如果要通過<script>元素來包含外部 JavaScript 文件,那么 src 屬性就是必需的。這個屬性的值
是一個指向外部 JavaScript 文件的鏈接,例如:
<script type=\"text/javascript\" src=\"example.js\"></script>
在這個例子中,外部文件 example.js 將被加載到當前頁面中。外部文件只須包含通常要放在開始
的<script>和結(jié)束的</script>之間的那些 JavaScript 代碼即可。與解析嵌入式 JavaScript 代碼一樣,
在解析外部 JavaScript 文件(包括下載該文件)時,頁面的處理也會暫時停止。如果是在 XHTML 文檔
中,也可以省略前面示例代碼中結(jié)束的</script>標簽,例如:
<script type=\"text/javascript\" src=\"example.js\" />
但是,不能在 HTML 文檔使用這種語法。原因是這種語法不符合 HTML 規(guī)范,而且也得不到某些
瀏覽器(尤其是 IE)的正確解析。
圖靈社區(qū)會員 StinkBC(StinkBC@gmail.com) 專享 尊重版權(quán)
12 第 2 章 在 HTML 中使用 JavaScript
按照慣例,外部 JavaScript 文件帶有.js 擴展名。但這個擴展名不是必需的,因為
瀏覽器不會檢查包含 JavaScript 的文件的擴展名。這樣一來,使用 JSP、PHP 或其他
服務器端語言動態(tài)生成 JavaScript 代碼也就成為了可能。但是,服務器通常還是需要
看擴展名決定為響應應用哪種 MIME 類型。如果不使用.js 擴展名,請確保服務器能
返回正確的 MIME 類型。
需要注意的是,帶有 src 屬性的<script>元素不應該在其<script>和</script>標簽之間再
包含額外的 JavaScript 代碼。如果包含了嵌入的代碼,則只會下載并執(zhí)行外部腳本文件,嵌入的代碼
會被忽略。
另外,通過<script>元素的 src 屬性還可以包含來自外部域的 JavaScript 文件。這一點既讓
<script>元素倍顯強大,又讓它備受爭議。在這一點上,<script>與<img>元素非常相似,即它的 src
屬性可以是指向當前 HTML 頁面所在域之外的某個域中的完整 URL,例如:
<script type=\"text/javascript\" src=\"http://www.somewhere.com/afile.js\"></script>
這樣,位于外部域中的代碼也會被加載和解析,就像這些代碼位于加載它們的頁面中一樣。利用這
一點就可以在必要時通過不同的域來提供 JavaScript 文件。不過,在訪問自己不能控制的服務器上的
JavaScript 文件時則要多加小心。如果不幸遇到了懷有惡意的程序員,那他們隨時都可能替換該文件中
的代碼。因此,如果想包含來自不同域的代碼,則要么你是那個域的所有者,要么那個域的所有者值得
信賴。
無論如何包含代碼,只要不存在 defer 和 async 屬性,瀏覽器都會按照<script>元素在頁面中
出現(xiàn)的先后順序?qū)λ鼈円来芜M行解析。換句話說,在第一個<script>元素包含的代碼解析完成后,第
二個<script>包含的代碼才會被解析,然后才是第三個、第四個……
2.1.1 標簽的位置
按照傳統(tǒng)的做法,所有<script>元素都應該放在頁面的<head>元素中,例如:
<!DOCTYPE html>
<html>
<head>
<title>Example HTML Page</title>
<script type=\"text/javascript\" src=\"example1.js\"></script>
<script type=\"text/javascript\" src=\"example2.js\"></script>
</head>
<body>
<!-- 這里放內(nèi)容 -->
</body>
</html>
這種做法的目的就是把所有外部文件(包括 CSS 文件和 JavaScript 文件)的引用都放在相同的地方。
可是,在文檔的<head>元素中包含所有 JavaScript 文件,意味著必須等到全部 JavaScript 代碼都被下載、
解析和執(zhí)行完成以后,才能開始呈現(xiàn)頁面的內(nèi)容(瀏覽器在遇到<body>標簽時才開始呈現(xiàn)內(nèi)容)。對于
那些需要很多 JavaScript 代碼的頁面來說,這無疑會導致瀏覽器在呈現(xiàn)頁面時出現(xiàn)明顯的延遲,而延遲
期間的瀏覽器窗口中將是一片空白。為了避免這個問題,現(xiàn)代 Web 應用程序一般都把全部 JavaScript 引
用放在<body>元素中頁面內(nèi)容的后面,如下例所示:
圖靈社區(qū)會員 StinkBC(StinkBC@gmail.com) 專享 尊重版權(quán)
2.1 <script>元素 13
1
2
3
4
5
13
6
7
8
9
10
11
12
<!DOCTYPE html>
<html>
<head>
<title>Example HTML Page</title>
</head>
<body>
<!-- 這里放內(nèi)容 -->
<script type=\"text/javascript\" src=\"example1.js\"></script>
<script type=\"text/javascript\" src=\"example2.js\"></script>
</body>
</html>
這樣,在解析包含的 JavaScript 代碼之前,頁面的內(nèi)容將完全呈現(xiàn)在瀏覽器中。而用戶也會因為瀏
覽器窗口顯示空白頁面的時間縮短而感到打開頁面的速度加快了。
2.1.2 延遲腳本
HTML 4.01 為<script>標簽定義了 defer 屬性。這個屬性的用途是表明腳本在執(zhí)行時不會影響頁
面的構(gòu)造。也就是說,腳本會被延遲到整個頁面都解析完畢后再運行。因此,在<script>元素中設置
defer 屬性,相當于告訴瀏覽器立即下載,但延遲執(zhí)行。
<!DOCTYPE html>
<html>
<head>
<title>Example HTML Page</title>
<script type=\"text/javascript\" defer=\"defer\" src=\"example1.js\"></script>
<script type=\"text/javascript\" defer=\"defer\" src=\"example2.js\"></script>
</head>
<body>
<!-- 這里放內(nèi)容 -->
</body>
</html>
在這個例子中,雖然我們把<script>元素放在了文檔的<head>元素中,但其中包含的腳本將延遲
到瀏覽器遇到</html>標簽后再執(zhí)行。HTML5 規(guī)范要求腳本按照它們出現(xiàn)的先后順序執(zhí)行,因此第一
個延遲腳本會先于第二個延遲腳本執(zhí)行,而這兩個腳本會先于 DOMContentLoaded 事件(詳見第 13 章)
執(zhí)行。在現(xiàn)實當中,延遲腳本并不一定會按照順序執(zhí)行,也不一定會在 DOMContentLoaded 事件觸發(fā)
前執(zhí)行,因此最好只包含一個延遲腳本。
前面提到過,defer 屬性只適用于外部腳本文件。這一點在 HTML5 中已經(jīng)明確規(guī)定,因此支持
HTML5 的實現(xiàn)會忽略給嵌入腳本設置的 defer 屬性。IE4~IE7 還支持對嵌入腳本的 defer 屬性,但
IE8 及之后版本則完全支持 HTML5 規(guī)定的行為。
IE4、Firefox 3.5、Safari 5 和 Chrome 是最早支持 defer 屬性的瀏覽器。其他瀏覽器會忽略這個屬
性,像平常一樣處理腳本。為此,把延遲腳本放在頁面底部仍然是最佳選擇。
在 XHTML 文檔中,要把 defer 屬性設置為 defer=\"defer\"。
2.1.3 異步腳本
HTML5 為<script>元素定義了 async 屬性。這個屬性與 defer 屬性類似,都用于改變處理腳本
圖靈社區(qū)會員 StinkBC(StinkBC@gmail.com) 專享 尊重版權(quán)
14 第 2 章 在 HTML 中使用 JavaScript
的行為。同樣與 defer 類似,async 只適用于外部腳本文件,并告訴瀏覽器立即下載文件。但與 defer
不同的是,標記為 async 的腳本并不保證按照指定它們的先后順序執(zhí)行。例如:
<!DOCTYPE html>
<html>
<head>
<title>Example HTML Page</title>
<script type=\"text/javascript\" async src=\"example1.js\"></script>
<script type=\"text/javascript\" async src=\"example2.js\"></script>
</head>
<body>
<!-- 這里放內(nèi)容 -->
</body>
</html>
在以上代碼中,第二個腳本文件可能會在第一個腳本文件之前執(zhí)行。因此,確保兩者之間互不依賴
非常重要。指定 async 屬性的目的是不讓頁面等待兩個腳本下載和執(zhí)行,從而異步加載頁面其他內(nèi)容。
為此,建議異步腳本不要在加載期間修改 DOM。
異步腳本一定會在頁面的 load 事件前執(zhí)行,但可能會在 DOMContentLoaded 事件觸發(fā)之前或之
后執(zhí)行。支持異步腳本的瀏覽器有 Firefox 3.6、Safari 5 和 Chrome。
在 XHTML 文檔中,要把 async 屬性設置為 async=\"async\"。
2.1.4 在XHTML中的用法①
可擴展超文本標記語言,即 XHTML(Extensible HyperText Markup Language),是將 HTML 作為
XML 的應用而重新定義的一個標準。編寫 XHTML 代碼的規(guī)則要比編寫 HTML 嚴格得多,而且直接影
響能否在嵌入 JavaScript 代碼時使用<script/>標簽。以下面的代碼塊為例,雖然它們在 HTML 中是有
效的,但在 XHTML 中則是無效的。
<script type=\"text/javascript\">
function compare(a, b) {
if (a < b) {
alert(\"A is less than B\");
} else if (a > b) {
alert(\"A is greater than B\");
} else {
alert(\"A is equal to B\");
}
}
</script>
在 HTML 中,有特殊的規(guī)則用以確定<script>元素中的哪些內(nèi)容可以被解析,但這些特殊的規(guī)則
在 XHTML 中不適用。這里比較語句 a < b 中的小于號(<)在 XHTML 中將被當作開始一個新標簽來
解析。但是作為標簽來講,小于號后面不能跟空格,因此就會導致語法錯誤。
——————————
① HTML5 正快速地被前端開發(fā)人員采用,建議讀者在學習和開發(fā)中遵循 HTML5 標準,本節(jié)內(nèi)容可以跳過。
圖靈社區(qū)會員 StinkBC(StinkBC@gmail.com) 專享 尊重版權(quán)
2.1 <script>元素 15
1
2
3
4
5
13
6
7
8
9
10
11
12
避免在 XHTML 中出現(xiàn)類似語法錯誤的方法有兩個。一是用相應的 HTML 實體(<)替換代碼
中所有的小于號(<),替換后的代碼類似如下所示:
<script type=\"text/javascript\">
function compare(a, b) {
if (a < b) {
alert(\"A is less than B\");
} else if (a > b) {
alert(\"A is greater than B\");
} else {
alert(\"A is equal to B\");
}
}
</script>
雖然這樣可以讓代碼在 XHTML 中正常運行,但卻導致代碼不好理解了。為此,我們可以考慮采用
另一個方法。
保證讓相同代碼在 XHTML 中正常運行的第二個方法,就是用一個 CData 片段來包含 JavaScript 代
碼。在 XHTML(XML)中,CData 片段是文檔中的一個特殊區(qū)域,這個區(qū)域中可以包含不需要解析的
任意格式的文本內(nèi)容。因此,在 CData 片段中就可以使用任意字符——小于號當然也沒有問題,而且不
會導致語法錯誤。引入 CData 片段后的 JavaScript 代碼塊如下所示:
<script type=\"text/javascript\"><![CDATA[
function compare(a, b) {
if (a < b) {
alert(\"A is less than B\");
} else if (a > b) {
alert(\"A is greater than B\");
} else {
alert(\"A is equal to B\");
}
}
]]></script>
在兼容 XHTML 的瀏覽器中,這個方法可以解決問題。但實際上,還有不少瀏覽器不兼容 XHTML,
因而不支持 CData 片段。怎么辦呢?再使用 JavaScript 注釋將 CData 標記注釋掉就可以了:
<script type=\"text/javascript\">
//<![CDATA[
function compare(a, b) {
if (a < b) {
alert(\"A is less than B\");
} else if (a > b) {
alert(\"A is greater than B\");
} else {
alert(\"A is equal to B\");
}
}
//]]>
</script>
這種格式在所有現(xiàn)代瀏覽器中都可以正常使用。雖然有幾分 hack 的味道,但它能通過 XHTML 驗
證,而且對 XHTML 之前的瀏覽器也會平穩(wěn)退化。
圖靈社區(qū)會員 StinkBC(StinkBC@gmail.com) 專享 尊重版權(quán)
16 第 2 章 在 HTML 中使用 JavaScript
在將頁面的 MIME 類型指定為\"application/xhtml+xml\"的情況下會觸發(fā)
XHTML 模式。并不是所有瀏覽器都支持以這種方式提供 XHTML 文檔。
2.1.5 不推薦使用的語法
在最早引入<script>元素的時候,該元素與傳統(tǒng) HTML 的解析規(guī)則是有沖突的。由于要對這個元
素應用特殊的解析規(guī)則,因此在那些不支持 JavaScript 的瀏覽器(最典型的是 Mosaic)中就會導致問題。
具體來說,不支持 JavaScript 的瀏覽器會把<script>元素的內(nèi)容直接輸出到頁面中,因而會破壞頁面的
布局和外觀。
Netscape 與 Mosaic 協(xié)商并提出了一個解決方案,讓不支持<script>元素的瀏覽器能夠隱藏嵌入的
JavaScript 代碼。這個方案就是把 JavaScript 代碼包含在一個 HTML 注釋中,像下面這樣:
<script><!--
function sayHi(){
alert(\"Hi!\");
}
//--></script>
給腳本加上 HTML 注釋后,Mosaic 等瀏覽器就會忽略<script>標簽中的內(nèi)容;而那些支持
JavaScript 的瀏覽器在遇到這種情況時,則必須進一步確認其中是否包含需要解析的 JavaScript 代碼。
雖然這種注釋 JavaScript 代碼的格式得到了所有瀏覽器的認可,也能被正確解釋,但由于所有瀏覽
器都已經(jīng)支持 JavaScript,因此也就沒有必要再使用這種格式了。在 XHTML 模式下,因為腳本包含在
XML 注釋中,所以腳本會被忽略。
2.2 嵌入代碼與外部文件
在 HTML 中嵌入 JavaScript 代碼雖然沒有問題,但一般認為最好的做法還是盡可能使用外部文件來
包含 JavaScript 代碼。不過,并不存在必須使用外部文件的硬性規(guī)定,但支持使用外部文件的人多會強
調(diào)如下優(yōu)點。
? 可維護性:遍及不同 HTML 頁面的 JavaScript 會造成維護問題。但把所有 JavaScript 文件都放在
一個文件夾中,維護起來就輕松多了。而且開發(fā)人員因此也能夠在不觸及 HTML 標記的情況下,
集中精力編輯 JavaScript 代碼。
? 可緩存:瀏覽器能夠根據(jù)具體的設置緩存鏈接的所有外部 JavaScript 文件。也就是說,如果有兩個
頁面都使用同一個文件,那么這個文件只需下載一次。因此,最終結(jié)果就是能夠加快頁面加載的
速度。
? 適應未來:通過外部文件來包含 JavaScript 無須使用前面提到 XHTML 或注釋 hack。HTML 和
XHTML 包含外部文件的語法是相同的。
2.3 文檔模式
IE5.5 引入了文檔模式的概念,而這個概念是通過使用文檔類型(doctype)切換實現(xiàn)的。最初的兩
圖靈社區(qū)會員 StinkBC(StinkBC@gmail.com) 專享 尊重版權(quán)
2.3 文檔模式 17
1
2
3
4
5
13
6
7
8
9
10
11
12
種文檔模式是:混雜模式(quirks mode)①和標準模式(standards mode)?;祀s模式會讓 IE 的行為與(包
含非標準特性的)IE5 相同,而標準模式則讓 IE 的行為更接近標準行為。雖然這兩種模式主要影響 CSS
內(nèi)容的呈現(xiàn),但在某些情況下也會影響到 JavaScript 的解釋執(zhí)行。本書將在必要時再討論這些因文檔模
式而影響 JavaScript 執(zhí)行的情況。
在 IE 引入文檔模式的概念后,其他瀏覽器也紛紛效仿。在此之后,IE 又提出一種所謂的準標準模
式(almost standards mode)。這種模式下的瀏覽器特性有很多都是符合標準的,但也不盡然。不標準的
地方主要體現(xiàn)在處理圖片間隙的時候(在表格中使用圖片時問題最明顯)。
如果在文檔開始處沒有發(fā)現(xiàn)文檔類型聲明,則所有瀏覽器都會默認開啟混雜模式。但采用混雜模式
不是什么值得推薦的做法,因為不同瀏覽器在這種模式下的行為差異非常大,如果不使用某些 hack 技
術(shù),跨瀏覽器的行為根本就沒有一致性可言。
對于標準模式,可以通過使用下面任何一種文檔類型來開啟:
<!-- HTML 4.01 嚴格型 -->
<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01//EN\"
\"http://www.w3.org/TR/html4/strict.dtd\">
<!-- XHTML 1.0 嚴格型 -->
<!DOCTYPE html PUBLIC
\"-//W3C//DTD XHTML 1.0 Strict//EN\"
\"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd\">
<!-- HTML 5 -->
<!DOCTYPE html>
而對于準標準模式,則可以通過使用過渡型(transitional)或框架集型(frameset)文檔類型來觸發(fā),
如下所示:
<!-- HTML 4.01 過渡型 -->
<!DOCTYPE HTML PUBLIC
\"-//W3C//DTD HTML 4.01 Transitional//EN\"
\"http://www.w3.org/TR/html4/loose.dtd\">
<!-- HTML 4.01 框架集型 -->
<!DOCTYPE HTML PUBLIC
\"-//W3C//DTD HTML 4.01 Frameset//EN\"
\"http://www.w3.org/TR/html4/frameset.dtd\">
<!-- XHTML 1.0 過渡型 -->
<!DOCTYPE html PUBLIC
\"-//W3C//DTD XHTML 1.0 Transitional//EN\"
\"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd\">
<!-- XHTML 1.0 框架集型 -->
<!DOCTYPE html PUBLIC
\"-//W3C//DTD XHTML 1.0 Frameset//EN\"
\"http://www.w3.org/TR/xhtml1/DTD/xhtml1-frameset.dtd\">
準標準模式與標準模式非常接近,它們的差異幾乎可以忽略不計。因此,當有人提到“標準模式”
時,有可能是指這兩種模式中的任何一種。而且,檢測文檔模式(本書后面將會討論)時也不會發(fā)現(xiàn)什
么不同。本書后面提到標準模式時,指的是除混雜模式之外的其他模式。
——————————
① 這里 quirks mode 的譯法源自 Firefox 3.5.5 中文版。
圖靈社區(qū)會員 StinkBC(StinkBC@gmail.com) 專享 尊重版權(quán)
18 第 2 章 在 HTML 中使用 JavaScript
2.4 <noscript>元素
早期瀏覽器都面臨一個特殊的問題,即當瀏覽器不支持 JavaScript 時如何讓頁面平穩(wěn)地退化。對這
個問題的最終解決方案就是創(chuàng)造一個<noscript>元素,用以在不支持 JavaScript 的瀏覽器中顯示替代
的內(nèi)容。這個元素可以包含能夠出現(xiàn)在文檔<body>中的任何 HTML 元素——<script>元素除外。包含
在<noscript>元素中的內(nèi)容只有在下列情況下才會顯示出來:
? 瀏覽器不支持腳本;
? 瀏覽器支持腳本,但腳本被禁用。
符合上述任何一個條件,瀏覽器都會顯示<noscript>中的內(nèi)容。而在除此之外的其他情況下,瀏
覽器不會呈現(xiàn)<noscript>中的內(nèi)容。
請看下面這個簡單的例子:
<html>
<head>
<title>Example HTML Page</title>
<script type=\"text/javascript\" defer=\"defer\" src=\"example1.js\"></script>
<script type=\"text/javascript\" defer=\"defer\" src=\"example2.js\"></script>
</head>
<body>
<noscript>
<p>本頁面需要瀏覽器支持(啟用)JavaScript。
</noscript>
</body>
</html>
這個頁面會在腳本無效的情況下向用戶顯示一條消息。而在啟用了腳本的瀏覽器中,用戶永遠也不
會看到它——盡管它是頁面的一部分。
2.5 小結(jié)
把 JavaScript 插入到 HTML 頁面中要使用<script>元素。使用這個元素可以把 JavaScript 嵌入到
HTML 頁面中,讓腳本與標記混合在一起;也可以包含外部的 JavaScript 文件。而我們需要注意的地方有:
? 在包含外部 JavaScript 文件時,必須將 src 屬性設置為指向相應文件的 URL。而這個文件既可
以是與包含它的頁面位于同一個服務器上的文件,也可以是其他任何域中的文件。
? 所有<script>元素都會按照它們在頁面中出現(xiàn)的先后順序依次被解析。在不使用 defer 和
async 屬性的情況下,只有在解析完前面<script>元素中的代碼之后,才會開始解析后面
<script>元素中的代碼。
? 由于瀏覽器會先解析完不使用 defer 屬性的<script>元素中的代碼,然后再解析后面的內(nèi)容,
所以一般應該把<script>元素放在頁面最后,即主要內(nèi)容后面,</body>標簽前面。
? 使用 defer 屬性可以讓腳本在文檔完全呈現(xiàn)之后再執(zhí)行。延遲腳本總是按照指定它們的順序執(zhí)行。
? 使用 async 屬性可以表示當前腳本不必等待其他腳本,也不必阻塞文檔呈現(xiàn)。不能保證異步腳
本按照它們在頁面中出現(xiàn)的順序執(zhí)行。
另外,使用<noscript>元素可以指定在不支持腳本的瀏覽器中顯示的替代內(nèi)容。但在啟用了腳本
的情況下,瀏覽器不會顯示<noscript>元素中的任何內(nèi)容。
圖靈社區(qū)會員 StinkBC(StinkBC@gmail.com) 專享 尊重版權(quán)
3.1 語法 19
1
2
3
4
5
13
6
7
8
9
10
11
12
基 本 概 念
本章內(nèi)容
? 語法
? 數(shù)據(jù)類型
? 流控制語句
? 函數(shù)
何語言的核心都必然會描述這門語言最基本的工作原理。而描述的內(nèi)容通常都要涉及這門語
言的語法、操作符、數(shù)據(jù)類型、內(nèi)置功能等用于構(gòu)建復雜解決方案的基本概念。如前所述,
ECMA-262 通過叫做 ECMAScript 的“偽語言”為我們描述了 JavaScript 的所有這些基本概念。
目前,ECMA-262 第 3 版中定義的 ECMAScript 是各瀏覽器實現(xiàn)最多的一個版本。ECMA-262 第 5
版是瀏覽器接下來實現(xiàn)的版本,但截止到 2011 年底,還沒有瀏覽器完全實現(xiàn)了這個版本。為此,本章
將主要按照第 3 版定義的 ECMAScript 介紹這門語言的基本概念,并就第 5 版的變化給出說明。
3.1 語法
ECMAScript 的語法大量借鑒了 C 及其他類 C 語言(如 Java 和 Perl)的語法。因此,熟悉這些語言
的開發(fā)人員在接受 ECMAScript 更加寬松的語法時,一定會有一種輕松自在的感覺。
3.1.1 區(qū)分大小寫
要理解的第一個概念就是 ECMAScript 中的一切(變量、函數(shù)名和操作符)都區(qū)分大小寫。這也就
意味著,變量名 test 和變量名 Test 分別表示兩個不同的變量,而函數(shù)名不能使用 typeof,因為它
是一個關(guān)鍵字(3.2 節(jié)介紹關(guān)鍵字),但 typeOf 則完全可以是一個有效的函數(shù)名。
3.1.2 標識符
所謂標識符,就是指變量、函數(shù)、屬性的名字,或者函數(shù)的參數(shù)。標識符可以是按照下列格式規(guī)則
組合起來的一或多個字符:
? 第一個字符必須是一個字母、下劃線(_)或一個美元符號($);
? 其他字符可以是字母、下劃線、美元符號或數(shù)字。
標識符中的字母也可以包含擴展的 ASCII 或 Unicode 字母字符(如 à 和 ?),但我們不推薦這樣做。
按照慣例,ECMAScript 標識符采用駝峰大小寫格式,也就是第一個字母小寫,剩下的每個單詞的
首字母大寫,例如:
任
第 3 章
圖靈社區(qū)會員 StinkBC(StinkBC@gmail.com) 專享 尊重版權(quán)
20 第 3 章 基本概念
firstSecond
myCar
doSomethingImportant
雖然沒有誰強制要求必須采用這種格式,但為了與 ECMAScript 內(nèi)置的函數(shù)和對象命名格式保持一
致,可以將其當作一種最佳實踐。
不能把關(guān)鍵字、保留字、true、false 和 null 用作標識符。3.2節(jié)將介紹更多相
關(guān)內(nèi)容。
3.1.3 注釋
ECMAScript 使用 C 風格的注釋,包括單行注釋和塊級注釋。單行注釋以兩個斜杠開頭,如下所示:
// 單行注釋
塊級注釋以一個斜杠和一個星號(/*)開頭,以一個星號和一個斜杠(*/)結(jié)尾,如下所示:
/*
* 這是一個多行
* (塊級)注釋
*/
雖然上面注釋中的第二和第三行都以一個星號開頭,但這不是必需的。之所以添加那兩個星號,純
粹是為了提高注釋的可讀性(這種格式在企業(yè)級應用中用得比較多)。
3.1.4 嚴格模式
ECMAScript 5 引入了嚴格模式(strict mode)的概念。嚴格模式是為 JavaScript 定義了一種不同的
解析與執(zhí)行模型。在嚴格模式下,ECMAScript 3 中的一些不確定的行為將得到處理,而且對某些不安全
的操作也會拋出錯誤。要在整個腳本中啟用嚴格模式,可以在頂部添加如下代碼:
\"use strict\";
這行代碼看起來像是字符串,而且也沒有賦值給任何變量,但其實它是一個編譯指示(pragma),
用于告訴支持的 JavaScript 引擎切換到嚴格模式。這是為不破壞 ECMAScript 3 語法而特意選定的語法。
在函數(shù)內(nèi)部的上方包含這條編譯指示,也可以指定函數(shù)在嚴格模式下執(zhí)行:
function doSomething(){
\"use strict\";
//函數(shù)體
}
嚴格模式下,JavaScript 的執(zhí)行結(jié)果會有很大不同,因此本書將會隨時指出嚴格模式下的區(qū)別。支
持嚴格模式的瀏覽器包括 IE10+、Firefox 4+、Safari 5.1+、Opera 12+和 Chrome。
3.1.5 語句
ECMAScript 中的語句以一個分號結(jié)尾;如果省略分號,則由解析器確定語句的結(jié)尾,如下例所示:
圖靈社區(qū)會員 StinkBC(StinkBC@gmail.com) 專享 尊重版權(quán)
3.2 關(guān)鍵字和保留字 21
1
2
3
4
5
13
6
7
8
9
10
11
12
var sum = a + b // 即使沒有分號也是有效的語句——不推薦
var diff = a - b; // 有效的語句——推薦
雖然語句結(jié)尾的分號不是必需的,但我們建議任何時候都不要省略它。因為加上這個分號可以避免
很多錯誤(例如不完整的輸入),開發(fā)人員也可以放心地通過刪除多余的空格來壓縮 ECMAScript 代碼(代
碼行結(jié)尾處沒有分號會導致壓縮錯誤)。另外,加上分號也會在某些情況下增進代碼的性能,因為這樣
解析器就不必再花時間推測應該在哪里插入分號了。
可以使用 C 風格的語法把多條語句組合到一個代碼塊中,即代碼塊以左花括號({)開頭,以右花
括號(})結(jié)尾:
if (test){
test = false;
alert(test);
}
雖然條件控制語句(如 if 語句)只在執(zhí)行多條語句的情況下才要求使用代碼塊,但最佳實踐是始
終在控制語句中使用代碼塊——即使代碼塊中只有一條語句,例如:
if (test)
alert(test); // 有效但容易出錯,不要使用
if (test){ // 推薦使用
alert(test);
}
在控制語句中使用代碼塊可以讓編碼意圖更加清晰,而且也能降低修改代碼時出錯的幾率。
3.2 關(guān)鍵字和保留字
ECMA-262 描述了一組具有特定用途的關(guān)鍵字,這些關(guān)鍵字可用于表示控制語句的開始或結(jié)束,或
者用于執(zhí)行特定操作等。按照規(guī)則,關(guān)鍵字也是語言保留的,不能用作標識符。以下就是 ECMAScript
的全部關(guān)鍵字(帶*號上標的是第 5 版新增的關(guān)鍵字):
break do instanceof typeof
case else new var
catch finally return void
continue for switch while
debugger* function this with
default if throw
delete in try
ECMA-262 還描述了另外一組不能用作標識符的保留字。盡管保留字在這門語言中還沒有任何特定
的用途,但它們有可能在將來被用作關(guān)鍵字。以下是 ECMA-262 第 3 版定義的全部保留字:
abstract enum int short
boolean export interface static
byte extends long super
char final native synchronized
class float package throws
const goto private transient
debugger implements protected volatile
double import public
圖靈社區(qū)會員 StinkBC(StinkBC@gmail.com) 專享 尊重版權(quán)
22 第 3 章 基本概念
第 5 版把在非嚴格模式下運行時的保留字縮減為下列這些:
class enum extends super
const export import
在嚴格模式下,第 5 版還對以下保留字施加了限制:
implements package public
interface private static
let protected yield
注意,let 和 yield 是第 5 版新增的保留字;其他保留字都是第 3 版定義的。為了最大程度地保
證兼容性,建議讀者將第 3 版定義的保留字外加 let 和 yield 作為編程時的參考。
在實現(xiàn) ECMAScript 3 的 JavaScript 引擎中使用關(guān)鍵字作標識符,會導致“Identifier Expected”錯誤。
而使用保留字作標識符可能會也可能不會導致相同的錯誤,具體取決于特定的引擎。
第 5 版對使用關(guān)鍵字和保留字的規(guī)則進行了少許修改。關(guān)鍵字和保留字雖然仍然不能作為標識符使
用,但現(xiàn)在可以用作對象的屬性名。一般來說,最好都不要使用關(guān)鍵字和保留字作為標識符和屬性名,
以便與將來的 ECMAScript 版本兼容。
除了上面列出的保留字和關(guān)鍵字,ECMA-262 第 5 版對 eval 和 arguments 還施加了限制。在嚴
格模式下,這兩個名字也不能作為標識符或?qū)傩悦?,否則會拋出錯誤。
3.3 變量
ECMAScript 的變量是松散類型的,所謂松散類型就是可以用來保存任何類型的數(shù)據(jù)。換句話說,
每個變量僅僅是一個用于保存值的占位符而已。定義變量時要使用 var 操作符(注意 var 是一個關(guān)鍵
字),后跟變量名(即一個標識符),如下所示:
var message;
這行代碼定義了一個名為 message 的變量,該變量可以用來保存任何值(像這樣未經(jīng)過初始化的
變量,會保存一個特殊的值——undefined,相關(guān)內(nèi)容將在 3.4 節(jié)討論)。ECMAScript 也支持直接初始
化變量,因此在定義變量的同時就可以設置變量的值,如下所示:
var message = \"hi\";
在此,變量 message 中保存了一個字符串值\"hi\"。像這樣初始化變量并不會把它標記為字符串類型;
初始化的過程就是給變量賦一個值那么簡單。因此,可以在修改變量值的同時修改值的類型,如下所示:
var message = \"hi\";
message = 100; // 有效,但不推薦
在這個例子中,變量 message 一開始保存了一個字符串值\"hi\",然后該值又被一個數(shù)字值 100 取
代。雖然我們不建議修改變量所保存值的類型,但這種操作在 ECMAScript 中完全有效。
有一點必須注意,即用 var 操作符定義的變量將成為定義該變量的作用域中的局部變量。也就是說,
如果在函數(shù)中使用 var 定義一個變量,那么這個變量在函數(shù)退出后就會被銷毀,例如:
function test(){
var message = \"hi\"; // 局部變量
}
test();
alert(message); // 錯誤!
圖靈社區(qū)會員 StinkBC(StinkBC@gmail.com) 專享 尊重版權(quán)
3.4 數(shù)據(jù)類型 23
1
2
3
4
5
13
6
7
8
9
10
11
12
這里,變量 message 是在函數(shù)中使用 var 定義的。當函數(shù)被調(diào)用時,就會創(chuàng)建該變量并為其賦值。
而在此之后,這個變量又會立即被銷毀,因此例子中的下一行代碼就會導致錯誤。不過,可以像下面這
樣省略 var 操作符,從而創(chuàng)建一個全局變量:
function test(){
message = \"hi\"; // 全局變量
}
test();
alert(message); // \"hi\"
這個例子省略了 var 操作符,因而 message 就成了全局變量。這樣,只要調(diào)用過一次 test()函
數(shù),這個變量就有了定義,就可以在函數(shù)外部的任何地方被訪問到。
雖然省略 var 操作符可以定義全局變量,但這也不是我們推薦的做法。因為在局
部作用域中定義的全局變量很難維護,而且如果有意地忽略了 var 操作符,也會由于
相應變量不會馬上就有定義而導致不必要的混亂。給未經(jīng)聲明的變量賦值在嚴格模式
下會導致拋出 ReferenceError 錯誤。
可以使用一條語句定義多個變量,只要像下面這樣把每個變量(初始化或不初始化均可)用逗號分
隔開即可:
var message = \"hi\",
found = false,
age = 29;
這個例子定義并初始化了 3 個變量。同樣由于 ECMAScript 是松散類型的,因而使用不同類型初始
化變量的操作可以放在一條語句中來完成。雖然代碼里的換行和變量縮進不是必需的,但這樣做可以提
高可讀性。
在嚴格模式下,不能定義名為 eval 或 arguments 的變量,否則會導致語法錯誤。
3.4 數(shù)據(jù)類型
ECMAScript 中有 5 種簡單數(shù)據(jù)類型(也稱為基本數(shù)據(jù)類型):Undefined、Null、Boolean、Number
和 String。還有 1種復雜數(shù)據(jù)類型——Object,Object 本質(zhì)上是由一組無序的名值對組成的。ECMAScript
不支持任何創(chuàng)建自定義類型的機制,而所有值最終都將是上述 6 種數(shù)據(jù)類型之一。乍一看,好像只有 6
種數(shù)據(jù)類型不足以表示所有數(shù)據(jù);但是,由于 ECMAScript 數(shù)據(jù)類型具有動態(tài)性,因此的確沒有再定義
其他數(shù)據(jù)類型的必要了。
3.4.1 typeof操作符
鑒于 ECMAScript 是松散類型的,因此需要有一種手段來檢測給定變量的數(shù)據(jù)類型——typeof 就
是負責提供這方面信息的操作符。對一個值使用 typeof 操作符可能返回下列某個字符串:
? \"undefined\"——如果這個值未定義;
? \"boolean\"——如果這個值是布爾值;
? \"string\"——如果這個值是字符串;
圖靈社區(qū)會員 StinkBC(StinkBC@gmail.com) 專享 尊重版權(quán)
24 第 3 章 基本概念
? \"number\"——如果這個值是數(shù)值;
? \"object\"——如果這個值是對象或 null;
? \"function\"——如果這個值是函數(shù)。
下面是幾個使用 typeof 操作符的例子:
var message = \"some string\";
alert(typeof message); // \"string\"
alert(typeof(message)); // \"string\"
alert(typeof 95); // \"number\"
TypeofExample01.htm
這幾個例子說明,typeof 操作符的操作數(shù)可以是變量(message),也可以是數(shù)值字面量。注意,
typeof 是一個操作符而不是函數(shù),因此例子中的圓括號盡管可以使用,但不是必需的。
有些時候,typeof 操作符會返回一些令人迷惑但技術(shù)上卻正確的值。比如,調(diào)用 typeof null
會返回\"object\",因為特殊值 null 被認為是一個空的對象引用。Safari 5 及之前版本、Chrome 7 及之
前版本在對正則表達式調(diào)用 typeof 操作符時會返回\"function\",而其他瀏覽器在這種情況下會返回
\"object\"。
從技術(shù)角度講,函數(shù)在 ECMAScript 中是對象,不是一種數(shù)據(jù)類型。然而,函數(shù)也
確實有一些特殊的屬性,因此通過 typeof 操作符來區(qū)分函數(shù)和其他對象是有必要的。
3.4.2 Undefined類型
Undefined 類型只有一個值,即特殊的 undefined。在使用 var 聲明變量但未對其加以初始化時,
這個變量的值就是 undefined,例如:
var message;
alert(message == undefined); //true
UndefinedExample01.htm
這個例子只聲明了變量 message,但未對其進行初始化。比較這個變量與 undefined 字面量,結(jié)
果表明它們是相等的。這個例子與下面的例子是等價的:
var message = undefined;
alert(message == undefined); //true
UndefinedExample02.htm
這個例子使用 undefined 值顯式初始化了變量 message。但我們沒有必要這么做,因為未經(jīng)初始
化的值默認就會取得 undefined 值。
一般而言,不存在需要顯式地把一個變量設置為 undefined 值的情況。字面值
undefined 的主要目的是用于比較,而 ECMA-262 第 3 版之前的版本中并沒有規(guī)定
這個值。第 3 版引入這個值是為了正式區(qū)分空對象指針與未經(jīng)初始化的變量。
圖靈社區(qū)會員 StinkBC(StinkBC@gmail.com) 專享 尊重版權(quán)
3.4 數(shù)據(jù)類型 25
1
2
3
4
5
13
6
7
8
9
10
11
12
不過,包含 undefined 值的變量與尚未定義的變量還是不一樣的??纯聪旅孢@個例子:
var message; // 這個變量聲明之后默認取得了 undefined 值
// 下面這個變量并沒有聲明
// var age
alert(message); // \"undefined\"
alert(age); // 產(chǎn)生錯誤
UndefinedExample03.htm
運行以上代碼,第一個警告框會顯示變量 message 的值,即\"undefined\"。而第二個警告框——
由于傳遞給 alert()函數(shù)的是尚未聲明的變量 age——則會導致一個錯誤。對于尚未聲明過的變量,只
能執(zhí)行一項操作,即使用 typeof 操作符檢測其數(shù)據(jù)類型(對未經(jīng)聲明的變量調(diào)用 delete 不會導致錯
誤,但這樣做沒什么實際意義,而且在嚴格模式下確實會導致錯誤)。
然而,令人困惑的是:對未初始化的變量執(zhí)行 typeof 操作符會返回 undefined 值,而對未聲明
的變量執(zhí)行 typeof 操作符同樣也會返回 undefined 值。來看下面的例子:
var message; // 這個變量聲明之后默認取得了 undefined 值
// 下面這個變量并沒有聲明
// var age
alert(typeof message); // \"undefined\"
alert(typeof age); // \"undefined\"
UndefinedExample04.htm
結(jié)果表明,對未初始化和未聲明的變量執(zhí)行 typeof 操作符都返回了 undefined 值;這個結(jié)果有
其邏輯上的合理性。因為雖然這兩種變量從技術(shù)角度看有本質(zhì)區(qū)別,但實際上無論對哪種變量也不可能
執(zhí)行真正的操作。
即便未初始化的變量會自動被賦予 undefined 值,但顯式地初始化變量依然是
明智的選擇。如果能夠做到這一點,那么當 typeof 操作符返回\"undefined\"值時,
我們就知道被檢測的變量還沒有被聲明,而不是尚未初始化。
3.4.3 Null類型
Null 類型是第二個只有一個值的數(shù)據(jù)類型,這個特殊的值是 null。從邏輯角度來看,null 值表
示一個空對象指針,而這也正是使用 typeof 操作符檢測 null 值時會返回\"object\"的原因,如下面
的例子所示:
var car = null;
alert(typeof car); // \"object\"
NullExample01.htm
圖靈社區(qū)會員 StinkBC(StinkBC@gmail.com) 專享 尊重版權(quán)
26 第 3 章 基本概念
如果定義的變量準備在將來用于保存對象,那么最好將該變量初始化為 null 而不是其他值。這樣
一來,只要直接檢查 null 值就可以知道相應的變量是否已經(jīng)保存了一個對象的引用,如下面的例子
所示:
if (car != null){
// 對 car 對象執(zhí)行某些操作
}
實際上,undefined 值是派生自 null 值的,因此 ECMA-262 規(guī)定對它們的相等性測試要返回 true:
alert(null == undefined); //true
NullExample02.htm
這里,位于 null 和 undefined 之間的相等操作符(==)總是返回 true,不過要注意的是,這個
操作符出于比較的目的會轉(zhuǎn)換其操作數(shù)(本章后面將詳細介紹相關(guān)內(nèi)容)。
盡管 null 和 undefined 有這樣的關(guān)系,但它們的用途完全不同。如前所述,無論在什么情況下
都沒有必要把一個變量的值顯式地設置為 undefined,可是同樣的規(guī)則對 null 卻不適用。換句話說,
只要意在保存對象的變量還沒有真正保存對象,就應該明確地讓該變量保存 null 值。這樣做不僅可以
體現(xiàn) null 作為空對象指針的慣例,而且也有助于進一步區(qū)分 null 和 undefined。
3.4.4 Boolean類型
Boolean 類型是 ECMAScript 中使用得最多的一種類型,該類型只有兩個字面值:true 和 false。
這兩個值與數(shù)字值不是一回事,因此 true 不一定等于 1,而 false 也不一定等于 0。以下是為變量賦
Boolean 類型值的例子:
var found = true;
var lost = false;
需要注意的是,Boolean 類型的字面值 true 和 false 是區(qū)分大小寫的。也就是說,True 和 False
(以及其他的混合大小寫形式)都不是 Boolean 值,只是標識符。
雖然 Boolean 類型的字面值只有兩個,但 ECMAScript 中所有類型的值都有與這兩個 Boolean 值
等價的值。要將一個值轉(zhuǎn)換為其對應的 Boolean 值,可以調(diào)用轉(zhuǎn)型函數(shù) Boolean(),如下例所示:
var message = \"Hello world!\";
var messageAsBoolean = Boolean(message);
BooleanExample01.htm
在這個例子中,字符串 message 被轉(zhuǎn)換成了一個 Boolean 值,該值被保存在 messageAsBoolean
變量中。可以對任何數(shù)據(jù)類型的值調(diào)用 Boolean()函數(shù),而且總會返回一個 Boolean 值。至于返回的
這個值是 true 還是 false,取決于要轉(zhuǎn)換值的數(shù)據(jù)類型及其實際值。下表給出了各種數(shù)據(jù)類型及其對
應的轉(zhuǎn)換規(guī)則。
數(shù)據(jù)類型 轉(zhuǎn)換為true的值 轉(zhuǎn)換為false的值
Boolean true false
String 任何非空字符串 \"\"(空字符串)
圖靈社區(qū)會員 StinkBC(StinkBC@gmail.com) 專享 尊重版權(quán)
3.4 數(shù)據(jù)類型 27
1
2
3
4
5
13
6
7
8
9
10
11
12
(續(xù))
數(shù)據(jù)類型 轉(zhuǎn)換為true的值 轉(zhuǎn)換為false的值
Number 任何非零數(shù)字值(包括無窮大) 0和NaN(參見本章后面有關(guān)NaN的內(nèi)容)
Object 任何對象 null
Undefined n/a①
undefined
這些轉(zhuǎn)換規(guī)則對理解流控制語句(如 if 語句)自動執(zhí)行相應的 Boolean 轉(zhuǎn)換非常重要,請看下面
的代碼:
var message = \"Hello world!\";
if (message){
alert(\"Value is true\");
}
BooleanExample02.htm
運行這個示例,就會顯示一個警告框,因為字符串 message 被自動轉(zhuǎn)換成了對應的 Boolean 值
(true)。由于存在這種自動執(zhí)行的 Boolean 轉(zhuǎn)換,因此確切地知道在流控制語句中使用的是什么變量
至關(guān)重要。錯誤地使用一個對象而不是一個 Boolean 值,就有可能徹底改變應用程序的流程。
3.4.5 Number類型
Number 類型應該是 ECMAScript 中最令人關(guān)注的數(shù)據(jù)類型了,這種類型使用 IEEE754 格式來表示
整數(shù)和浮點數(shù)值(浮點數(shù)值在某些語言中也被稱為雙精度數(shù)值)。為支持各種數(shù)值類型,ECMA-262 定
義了不同的數(shù)值字面量格式。
最基本的數(shù)值字面量格式是十進制整數(shù),十進制整數(shù)可以像下面這樣直接在代碼中輸入:
var intNum = 55; // 整數(shù)
除了以十進制表示外,整數(shù)還可以通過八進制(以 8 為基數(shù))或十六進制(以 16 為基數(shù))的字面值
來表示。其中,八進制字面值的第一位必須是零(0),然后是八進制數(shù)字序列(0~7)。如果字面值中的
數(shù)值超出了范圍,那么前導零將被忽略,后面的數(shù)值將被當作十進制數(shù)值解析。請看下面的例子:
var octalNum1 = 070; // 八進制的 56
var octalNum2 = 079; // 無效的八進制數(shù)值——解析為 79
var octalNum3 = 08; // 無效的八進制數(shù)值——解析為 8
八進制字面量在嚴格模式下是無效的,會導致支持的 JavaScript 引擎拋出錯誤。
十六進制字面值的前兩位必須是 0x,后跟任何十六進制數(shù)字(0~9 及 A~F)。其中,字母 A~F
可以大寫,也可以小寫。如下面的例子所示:
var hexNum1 = 0xA; // 十六進制的 10
var hexNum2 = 0x1f; // 十六進制的 31
在進行算術(shù)計算時,所有以八進制和十六進制表示的數(shù)值最終都將被轉(zhuǎn)換成十進制數(shù)值。
——————————
① n/a(或 N/A),是 not applicable 的縮寫,意思是“不適用”。
圖靈社區(qū)會員 StinkBC(StinkBC@gmail.com) 專享 尊重版權(quán)
28 第 3 章 基本概念
鑒于 JavaScript 中保存數(shù)值的方式,可以保存正零(+0)和負零(?0)。正零和
負零被認為相等,但為了讀者更好地理解上下文,這里特別做此說明。
1. 浮點數(shù)值
所謂浮點數(shù)值,就是該數(shù)值中必須包含一個小數(shù)點,并且小數(shù)點后面必須至少有一位數(shù)字。雖然小
數(shù)點前面可以沒有整數(shù),但我們不推薦這種寫法。以下是浮點數(shù)值的幾個例子:
var floatNum1 = 1.1;
var floatNum2 = 0.1;
var floatNum3 = .1; // 有效,但不推薦
由于保存浮點數(shù)值需要的內(nèi)存空間是保存整數(shù)值的兩倍,因此 ECMAScript 會不失時機地將浮點數(shù)值
轉(zhuǎn)換為整數(shù)值。顯然,如果小數(shù)點后面沒有跟任何數(shù)字,那么這個數(shù)值就可以作為整數(shù)值來保存。同樣
地,如果浮點數(shù)值本身表示的就是一個整數(shù)(如 1.0),那么該值也會被轉(zhuǎn)換為整數(shù),如下面的例子所示:
var floatNum1 = 1.; // 小數(shù)點后面沒有數(shù)字——解析為 1
var floatNum2 = 10.0; // 整數(shù)——解析為 10
對于那些極大或極小的數(shù)值,可以用 e 表示法(即科學計數(shù)法)表示的浮點數(shù)值表示。用 e 表示法
表示的數(shù)值等于 e 前面的數(shù)值乘以 10 的指數(shù)次冪。ECMAScript 中 e 表示法的格式也是如此,即前面是
一個數(shù)值(可以是整數(shù)也可以是浮點數(shù)),中間是一個大寫或小寫的字母 E,后面是 10 的冪中的指數(shù),
該冪值將用來與前面的數(shù)相乘。下面是一個使用 e 表示法表示數(shù)值的例子:
var floatNum = 3.125e7; // 等于 31250000
在這個例子中,使用 e 表示法表示的變量 floatNum 的形式雖然簡潔,但它的實際值則是 31250000。
在此,e 表示法的實際含義就是“3.125 乘以 107
”。
也可以使用 e 表示法表示極小的數(shù)值,如 0.00000000000000003,這個數(shù)值可以使用更簡潔的 3e?17
表示。在默認情況下,ECMASctipt 會將那些小數(shù)點后面帶有 6 個零以上的浮點數(shù)值轉(zhuǎn)換為以 e 表示法
表示的數(shù)值(例如,0.0000003 會被轉(zhuǎn)換成 3e?7)。
浮點數(shù)值的最高精度是 17 位小數(shù),但在進行算術(shù)計算時其精確度遠遠不如整數(shù)。例如,0.1 加 0.2
的結(jié)果不是 0.3,而是 0.30000000000000004。這個小小的舍入誤差會導致無法測試特定的浮點數(shù)值。
例如:
if (a + b == 0.3){ // 不要做這樣的測試!
alert(\"You got 0.3.\");
}
在這個例子中,我們測試的是兩個數(shù)的和是不是等于 0.3。如果這兩個數(shù)是 0.05 和 0.25,或者是 0.15
和 0.15 都不會有問題。而如前所述,如果這兩個數(shù)是 0.1 和 0.2,那么測試將無法通過。因此,永遠不
要測試某個特定的浮點數(shù)值。
關(guān)于浮點數(shù)值計算會產(chǎn)生舍入誤差的問題,有一點需要明確:這是使用基于
IEEE754 數(shù)值的浮點計算的通病,ECMAScript 并非獨此一家;其他使用相同數(shù)值格
式的語言也存在這個問題。
圖靈社區(qū)會員 StinkBC(StinkBC@gmail.com) 專享 尊重版權(quán)
3.4 數(shù)據(jù)類型 29
1
2
3
4
5
13
6
7
8
9
10
11
12
2. 數(shù)值范圍
由于內(nèi)存的限制,ECMAScript 并不能保存世界上所有的數(shù)值。ECMAScript 能夠表示的最小數(shù)值保
存在 Number.MIN_VALUE 中——在大多數(shù)瀏覽器中,這個值是 5e-324;能夠表示的最大數(shù)值保存在
Number.MAX_VALUE 中——在大多數(shù)瀏覽器中,這個值是 1.7976931348623157e+308。如果某次計算的
結(jié)果得到了一個超出 JavaScript 數(shù)值范圍的值,那么這個數(shù)值將被自動轉(zhuǎn)換成特殊的 Infinity 值。具
體來說,如果這個數(shù)值是負數(shù),則會被轉(zhuǎn)換成-Infinity(負無窮),如果這個數(shù)值是正數(shù),則會被轉(zhuǎn)
換成 Infinity(正無窮)。
如上所述,如果某次計算返回了正或負的 Infinity 值,那么該值將無法繼續(xù)參與下一次的計算,
因為 Infinity 不是能夠參與計算的數(shù)值。要想確定一個數(shù)值是不是有窮的(換句話說,是不是位于最
小和最大的數(shù)值之間),可以使用 isFinite()函數(shù)。這個函數(shù)在參數(shù)位于最小與最大數(shù)值之間時會返
回 true,如下面的例子所示:
var result = Number.MAX_VALUE + Number.MAX_VALUE;
alert(isFinite(result)); //false
盡管在計算中很少出現(xiàn)某些值超出表示范圍的情況,但在執(zhí)行極小或極大數(shù)值的計算時,檢測監(jiān)控
這些值是可能的,也是必需的。
訪問 Number.NEGATIVE_INFINITY 和 Number.POSITIVE_INFINITY 也可以
得到負和正 Infinity 的值??梢韵胍姡@兩個屬性中分別保存著-Infinity 和
Infinity。
3. NaN
NaN,即非數(shù)值(Not a Number)是一個特殊的數(shù)值,這個數(shù)值用于表示一個本來要返回數(shù)值的操作數(shù)
未返回數(shù)值的情況(這樣就不會拋出錯誤了)。例如,在其他編程語言中,任何數(shù)值除以 0都會導致錯誤,
從而停止代碼執(zhí)行。但在 ECMAScript中,任何數(shù)值除以 0會返回 NaN①,因此不會影響其他代碼的執(zhí)行。
NaN 本身有兩個非同尋常的特點。首先,任何涉及 NaN 的操作(例如 NaN/10)都會返回 NaN,這
個特點在多步計算中有可能導致問題。其次,NaN 與任何值都不相等,包括 NaN 本身。例如,下面的代
碼會返回 false:
alert(NaN == NaN); //false
針對 NaN 的這兩個特點,ECMAScript 定義了 isNaN()函數(shù)。這個函數(shù)接受一個參數(shù),該參數(shù)可以
是任何類型,而函數(shù)會幫我們確定這個參數(shù)是否“不是數(shù)值”。isNaN()在接收到一個值之后,會嘗試
將這個值轉(zhuǎn)換為數(shù)值。某些不是數(shù)值的值會直接轉(zhuǎn)換為數(shù)值,例如字符串\"10\"或 Boolean 值。而任何
不能被轉(zhuǎn)換為數(shù)值的值都會導致這個函數(shù)返回 true。請看下面的例子:
alert(isNaN(NaN)); //true
alert(isNaN(10)); //false(10 是一個數(shù)值)
alert(isNaN(\"10\")); //false(可以被轉(zhuǎn)換成數(shù)值 10)
alert(isNaN(\"blue\")); //true(不能轉(zhuǎn)換成數(shù)值)
alert(isNaN(true)); //false(可以被轉(zhuǎn)換成數(shù)值 1)
NumberExample03.htm
——————————
① 原書如此,但實際上只有 0 除以 0 才會返回 NaN,正數(shù)除以 0 返回 Infinity,負數(shù)除以 0 返回-Infinity。
圖靈社區(qū)會員 StinkBC(StinkBC@gmail.com) 專享 尊重版權(quán)
30 第 3 章 基本概念
這個例子測試了 5 個不同的值。測試的第一個值是 NaN 本身,結(jié)果當然會返回 true。然后分別測
試了數(shù)值 10 和字符串\"10\",結(jié)果這兩個測試都返回了 false,因為前者本身就是數(shù)值,而后者可以被
轉(zhuǎn)換成數(shù)值。但是,字符串\"blue\"不能被轉(zhuǎn)換成數(shù)值,因此函數(shù)返回了 true。由于 Boolean 值 true
可以轉(zhuǎn)換成數(shù)值 1,因此函數(shù)返回 false。
盡管有點兒不可思議,但 isNaN()確實也適用于對象。在基于對象調(diào)用 isNaN()
函數(shù)時,會首先調(diào)用對象的 valueOf()方法,然后確定該方法返回的值是否可以轉(zhuǎn)
換為數(shù)值。如果不能,則基于這個返回值再調(diào)用 toString()方法,再測試返回值。
而這個過程也是 ECMAScript 中內(nèi)置函數(shù)和操作符的一般執(zhí)行流程,更詳細的內(nèi)容請
參見 3.5 節(jié)。
4. 數(shù)值轉(zhuǎn)換
有 3 個函數(shù)可以把非數(shù)值轉(zhuǎn)換為數(shù)值:Number()、parseInt()和 parseFloat()。第一個函數(shù),
即轉(zhuǎn)型函數(shù) Number()可以用于任何數(shù)據(jù)類型,而另兩個函數(shù)則專門用于把字符串轉(zhuǎn)換成數(shù)值。這 3 個
函數(shù)對于同樣的輸入會有返回不同的結(jié)果。
Number()函數(shù)的轉(zhuǎn)換規(guī)則如下。
? 如果是 Boolean 值,true 和 false 將分別被轉(zhuǎn)換為 1 和 0。
? 如果是數(shù)字值,只是簡單的傳入和返回。
? 如果是 null 值,返回 0。
? 如果是 undefined,返回 NaN。
? 如果是字符串,遵循下列規(guī)則:
? 如果字符串中只包含數(shù)字(包括前面帶正號或負號的情況),則將其轉(zhuǎn)換為十進制數(shù)值,即\"1\"
會變成 1,\"123\"會變成 123,而\"011\"會變成 11(注意:前導的零被忽略了);
? 如果字符串中包含有效的浮點格式,如\"1.1\",則將其轉(zhuǎn)換為對應的浮點數(shù)值(同樣,也會忽
略前導零);
? 如果字符串中包含有效的十六進制格式,例如\"0xf\",則將其轉(zhuǎn)換為相同大小的十進制整
數(shù)值;
? 如果字符串是空的(不包含任何字符),則將其轉(zhuǎn)換為 0;
? 如果字符串中包含除上述格式之外的字符,則將其轉(zhuǎn)換為 NaN。
? 如果是對象,則調(diào)用對象的 valueOf()方法,然后依照前面的規(guī)則轉(zhuǎn)換返回的值。如果轉(zhuǎn)換
的結(jié)果是 NaN,則調(diào)用對象的 toString()方法,然后再次依照前面的規(guī)則轉(zhuǎn)換返回的字符
串值。
根據(jù)這么多的規(guī)則使用 Number()把各種數(shù)據(jù)類型轉(zhuǎn)換為數(shù)值確實有點復雜。下面還是給出幾個具
體的例子吧。
var num1 = Number(\"Hello world!\"); //NaN
var num2 = Number(\"\"); //0
var num3 = Number(\"000011\"); //11
var num4 = Number(true); //1
NumberExample04.htm
圖靈社區(qū)會員 StinkBC(StinkBC@gmail.com) 專享 尊重版權(quán)
3.4 數(shù)據(jù)類型 31
1
2
3
4
5
13
6
7
8
9
10
11
12
首先,字符串\"Hello world!\"會被轉(zhuǎn)換為 NaN,因為其中不包含任何有意義的數(shù)字值??兆址?/p>
會被轉(zhuǎn)換為 0。字符串\"000011\"會被轉(zhuǎn)換為 11,因為忽略了其前導的零。最后,true 值被轉(zhuǎn)換為 1。
一元加操作符(3.5.1 節(jié)將介紹)的操作與 Number()函數(shù)相同。
由于 Number()函數(shù)在轉(zhuǎn)換字符串時比較復雜而且不夠合理,因此在處理整數(shù)的時候更常用的是
parseInt()函數(shù)。parseInt()函數(shù)在轉(zhuǎn)換字符串時,更多的是看其是否符合數(shù)值模式。它會忽略字
符串前面的空格,直至找到第一個非空格字符。如果第一個字符不是數(shù)字字符或者負號,parseInt()
就會返回 NaN;也就是說,用 parseInt()轉(zhuǎn)換空字符串會返回 NaN(Number()對空字符返回 0)。如
果第一個字符是數(shù)字字符,parseInt()會繼續(xù)解析第二個字符,直到解析完所有后續(xù)字符或者遇到了
一個非數(shù)字字符。例如,\"1234blue\"會被轉(zhuǎn)換為 1234,因為\"blue\"會被完全忽略。類似地,\"22.5\"
會被轉(zhuǎn)換為 22,因為小數(shù)點并不是有效的數(shù)字字符。
如果字符串中的第一個字符是數(shù)字字符,parseInt()也能夠識別出各種整數(shù)格式(即前面討論的
十進制、八進制和十六進制數(shù))。也就是說,如果字符串以\"0x\"開頭且后跟數(shù)字字符,就會將其當作一
個十六進制整數(shù);如果字符串以\"0\"開頭且后跟數(shù)字字符,則會將其當作一個八進制數(shù)來解析。
為了更好地理解 parseInt()函數(shù)的轉(zhuǎn)換規(guī)則,下面給出一些例子:
var num1 = parseInt(\"1234blue\"); // 1234
var num2 = parseInt(\"\"); // NaN
var num3 = parseInt(\"0xA\"); // 10(十六進制數(shù))
var num4 = parseInt(22.5); // 22
var num5 = parseInt(\"070\"); // 56(八進制數(shù))
var num6 = parseInt(\"70\"); // 70(十進制數(shù))
var num7 = parseInt(\"0xf\"); // 15(十六進制數(shù))
NumberExample05.htm
在使用 parseInt()解析像八進制字面量的字符串時,ECMAScript 3 和 5 存在分歧。例如:
//ECMAScript 3 認為是 56(八進制),ECMAScript 5 認為是 70(十進制)
var num = parseInt(\"070\");
在 ECMAScript 3 JavaScript 引擎中,\"070\"被當成八進制字面量,因此轉(zhuǎn)換后的值是十進制的 56。
而在 ECMAScript 5 JavaScript 引擎中,parseInt()已經(jīng)不具有解析八進制值的能力,因此前導的零會
被認為無效,從而將這個值當成\"70\",結(jié)果就得到十進制的 70。在 ECMAScript 5 中,即使是在非嚴格
模式下也會如此。
為了消除在使用 parseInt()函數(shù)時可能導致的上述困惑,可以為這個函數(shù)提供第二個參數(shù):轉(zhuǎn)換
時使用的基數(shù)(即多少進制)。如果知道要解析的值是十六進制格式的字符串,那么指定基數(shù) 16 作為第
二個參數(shù),可以保證得到正確的結(jié)果,例如:
var num = parseInt(\"0xAF\", 16); //175
實際上,如果指定了 16 作為第二個參數(shù),字符串可以不帶前面的\"0x\",如下所示:
var num1 = parseInt(\"AF\", 16); //175
var num2 = parseInt(\"AF\"); //NaN
NumberExample06.htm
圖靈社區(qū)會員 StinkBC(StinkBC@gmail.com) 專享 尊重版權(quán)
32 第 3 章 基本概念
這個例子中的第一個轉(zhuǎn)換成功了,而第二個則失敗了。差別在于第一個轉(zhuǎn)換傳入了基數(shù),明確告訴
parseInt()要解析一個十六進制格式的字符串;而第二個轉(zhuǎn)換發(fā)現(xiàn)第一個字符不是數(shù)字字符,因此就
自動終止了。
指定基數(shù)會影響到轉(zhuǎn)換的輸出結(jié)果。例如:
var num1 = parseInt(\"10\", 2); //2 (按二進制解析)
var num2 = parseInt(\"10\", 8); //8 (按八進制解析)
var num3 = parseInt(\"10\", 10); //10 (按十進制解析)
var num4 = parseInt(\"10\", 16); //16 (按十六進制解析)
NumberExample07.htm
不指定基數(shù)意味著讓 parseInt()決定如何解析輸入的字符串,因此為了避免錯誤的解析,我們建
議無論在什么情況下都明確指定基數(shù)。
多數(shù)情況下,我們要解析的都是十進制數(shù)值,因此始終將 10 作為第二個參數(shù)是
非常必要的。
與 parseInt()函數(shù)類似,parseFloat()也是從第一個字符(位置 0)開始解析每個字符。而且
也是一直解析到字符串末尾,或者解析到遇見一個無效的浮點數(shù)字字符為止。也就是說,字符串中的第
一個小數(shù)點是有效的,而第二個小數(shù)點就是無效的了,因此它后面的字符串將被忽略。舉例來說,
\"22.34.5\"將會被轉(zhuǎn)換為 22.34。
除了第一個小數(shù)點有效之外,parseFloat()與 parseInt()的第二個區(qū)別在于它始終都會忽略前導
的零。parseFloat()可以識別前面討論過的所有浮點數(shù)值格式,也包括十進制整數(shù)格式。但十六進制格
式的字符串則始終會被轉(zhuǎn)換成 0。由于 parseFloat()只解析十進制值,因此它沒有用第二個參數(shù)指定基
數(shù)的用法。最后還要注意一點:如果字符串包含的是一個可解析為整數(shù)的數(shù)(沒有小數(shù)點,或者小數(shù)點后
都是零),parseFloat()會返回整數(shù)。以下是使用 parseFloat()轉(zhuǎn)換數(shù)值的幾個典型示例。
var num1 = parseFloat(\"1234blue\"); //1234 (整數(shù))
var num2 = parseFloat(\"0xA\"); //0
var num3 = parseFloat(\"22.5\"); //22.5
var num4 = parseFloat(\"22.34.5\"); //22.34
var num5 = parseFloat(\"0908.5\"); //908.5
var num6 = parseFloat(\"3.125e7\"); //31250000
NumberExample08.htm
3.4.6 String類型
String 類型用于表示由零或多個 16 位 Unicode 字符組成的字符序列,即字符串。字符串可以由雙
引號(\")或單引號(')表示,因此下面兩種字符串的寫法都是有效的:
var firstName = \"Nicholas\";
var lastName = 'Zakas';
與 PHP 中的雙引號和單引號會影響對字符串的解釋方式不同,ECMAScript 中的這兩種語法形式?jīng)]
有什么區(qū)別。用雙引號表示的字符串和用單引號表示的字符串完全相同。不過,以雙引號開頭的字符串
圖靈社區(qū)會員 StinkBC(StinkBC@gmail.com) 專享 尊重版權(quán)