第1部分 語言基礎
第1章 十年JavaScript 3
1.1 網頁中的代碼 3
1.1.1 新鮮的玩意兒 3
1.1.2 第一段在網頁中的代碼 4
1.1.3 最初的價值 5
1.2 用JavaScript來寫瀏覽器上的應用 7
1.2.1 我要做一個聊天室 7
1.2.2 Flash的一席之地 9
1.2.3 RWC與RIA之爭 10
1.3 沒有框架與庫的語言能怎樣發展呢 12
1.3.1 做一個框架 12
1.3.2 重寫框架的語言層 15
1.3.3 富瀏覽器端開發與AJAX 16
1.4 語言的進化 18
1.4.1 Qomo的重生 18
1.4.2 QoBean是對語言的重新組織 18
1.4.3 JavaScript作為一門語言的進化 19
1.5 為JavaScript正名 22
1.5.1 JavaScript 22
1.5.2 Core JavaScript 23
1.5.3 SpiderMonkey JavaScript 24
1.5.4 ECMAScript 24
1.5.5 JScript 25
1.5.6 總述 25
1.6 JavaScript的應用環境 26
1.6.1 宿主環境 27
1.6.2 外殼程序 28
1.6.3 運行期環境 29
第2章 JavaScript的語法 31
2.1 語法綜述 31
2.1.1 標識符所綁定的語義 32
2.1.2 識彆語法錯誤與運行錯誤 33
2.2 JavaScript的語法:變量聲明 33
2.2.1 變量的數據類型 34
2.2.1.1 基本數據類型 34
2.2.1.2 值類型與引用類型 35
2.2.2 變量聲明 36
2.2.3 變量與直接量 37
2.2.3.1 字符串直接量、轉義符 38
2.2.3.2 數值直接量 40
2.2.4 函數聲明 41
2.3 JavaScript的語法:錶達式運算 42
2.3.1 一般錶達式運算 43
2.3.2 邏輯運算 44
2.3.3 字符串運算 45
2.3.4 比較運算 46
2.3.4.1 等值檢測 46
2.3.4.2 序列檢測 48
2.3.5 賦值運算 50
2.3.6 函數調用 51
2.3.7 特殊作用的運算符 51
2.3.8 運算優先級 53
2.4 JavaScript的語法:語句 55
2.4.1 錶達式語句 56
2.4.1.1 一般錶達式語句 57
2.4.1.2 賦值語句與隱式的變量聲明 59
2.4.1.3 (顯式的)變量聲明語句 59
2.4.1.4 函數調用語句 61
2.4.2 分支語句 65
2.4.2.1 條件分支語句(if語句) 65
2.4.2.2 多重分支語句(switch語句) 66
2.4.3 循環語句 68
2.4.4 流程控製:一般子句 70
2.4.4.1 標簽聲明 70
2.4.4.2 break子句 71
2.4.4.3 continue子句 73
2.4.4.4 return子句 75
2.4.5 流程控製:異常 75
2.5 麵嚮對象編程的語法概要 77
2.5.1 對象直接量聲明與實例創建 78
2.5.1.1 使用構造器創建對象實例 78
2.5.1.2 對象直接量聲明 81
2.5.1.3 數組直接量聲明 82
2.5.1.4 正則錶達式直接量聲明 83
2.5.1.5 【ES5】在對象直接量中使用屬性讀寫器 85
2.5.1.6 討論:初始器與直接量的區彆 86
2.5.2 對象成員 87
2.5.2.1 對象成員列舉、存取和刪除 87
2.5.2.2 屬性存取與方法調用 91
2.5.2.3 對象及其成員的檢查 92
2.5.2.4 可列舉性 94
2.5.3 默認對象的指定 95
2.6 【ES5】嚴格模式下的語法限製 96
2.6.1 語法限製 97
2.6.2 嚴格模式的範圍 99
2.7 運算符的二義性 100
2.7.1 加號“+”的二義性 102
2.7.2 括號“( )”的二義性 103
2.7.3 冒號“:”與標簽的二義性 105
2.7.4 大括號“{ }”的二義性 106
2.7.5 逗號“,”的二義性 109
2.7.6 方括號“[ ]”的二義性 111
第2部分 語言特性及基本應用
第3章 JavaScript的非函數式語言特性 117
3.1 概述 117
3.1.1 命令式語言與結構化編程 118
3.1.2 結構化的疑難 120
3.1.3 “麵嚮對象語言”是突破嗎 122
3.1.4 更高層次的抽象:接口 125
3.1.5 再論語言的分類 127
3.1.6 JavaScript的語源 129
3.2 基本語法的結構化含義 131
3.2.1 基本邏輯與代碼分塊 131
3.2.2 模塊化的層次:語法作用域 134
3.2.2.1 主要的語法作用域及其效果 135
3.2.2.2 語法作用域之間的相關性 138
3.2.3 執行流程及其變更 139
3.2.3.1 級彆2:“break <label>”等語法 140
3.2.3.2 級彆3:return子句 143
3.2.3.3 級彆4:throw語句 144
3.2.3.4 執行流程變更的內涵 145
3.2.4 模塊化的效果:變量作用域 147
3.2.4.1 級彆1:錶達式 148
3.2.4.2 級彆2:語句 149
3.2.4.3 級彆3:函數(局部) 150
3.2.4.4 級彆4:全局 151
3.2.4.5 變量作用域中的次序問題 153
3.2.4.6 變量作用域與變量的生存周期 154
3.2.5 語句的副作用 155
3.3 JavaScript中的原型繼承 157
3.3.1 空對象(null)與空的對象 158
3.3.2 原型繼承的基本性質 159
3.3.3 空的對象是所有對象的基礎 159
3.3.4 構造復製?寫時復製?還是讀遍曆? 160
3.3.5 構造過程:從函數到構造器 162
3.3.6 預定義屬性與方法 163
3.3.7 原型鏈的維護 165
3.3.7.1 兩個原型鏈 165
3.3.7.2 constructor屬性的維護 167
3.3.7.3 內部原型鏈的作用 170
3.3.7.4 【ES5】在SpiderMonkey與ES5中的原型鏈維護 170
3.3.8 原型繼承的實質 172
3.3.8.1 原型修改 172
3.3.8.2 原型繼承 173
3.3.8.3 原型繼承的實質:從無到有 174
3.3.8.4 如何理解“繼承來的成員” 175
3.4 JavaScript的對象係統 177
3.4.1 封裝 177
3.4.2 多態 179
3.4.3 事件 181
3.4.4 類抄寫?或原型繼承? 182
3.4.4.1 類抄寫 183
3.4.4.2 原型繼承存在的問題 186
3.4.4.3 如何選擇繼承的方式 186
3.4.5 JavaScript中的對象(構造器) 187
3.4.6 不能通過繼承得到的效果 190
3.5 【ES5】可定製的對象屬性 192
3.5.1 屬性描述符 192
3.5.1.1 (一般的)數據屬性描述符 193
3.5.1.2 (帶讀寫器的)存取屬性描述符 193
3.5.1.3 直接量形式的初始器是語法格式,而非描述符 194
3.5.2 定製對象屬性 195
3.5.2.1 屬性聲明以及獲取屬性描述符 195
3.5.2.2 新的對象創建方法:Object.create() 197
3.5.3 屬性狀態維護 198
3.5.3.1 取屬性列錶 198
3.5.3.2 使用defineProperty來維護屬性的性質 199
3.5.3.3 對於繼承自原型的屬性,修改其值的效果 200
3.5.3.4 重寫原型繼承來的屬性的描述符 201
第4章 JavaScript的函數式語言特性 203
4.1 概述 203
4.1.1 從代碼風格說起 204
4.1.2 為什麼常見的語言不贊同連續求值 204
4.1.3 函數式語言的淵源 206
4.2 函數式語言中的函數 208
4.2.1 函數是運算元 208
4.2.2 在函數內保存數據 209
4.2.3 函數內的運算對函數外無副作用 210
4.3 從運算式語言到函數式語言 211
4.3.1 JavaScript中的幾種連續運算 212
4.3.1.1 連續賦值 212
4.3.1.2 三元錶達式的連用 212
4.3.1.3 一些運算連用 214
4.3.1.4 函數與方法的調用 214
4.3.2 運算式語言 216
4.3.2.1 運算的實質是值運算 216
4.3.2.2 有趣的運算:在IE和J2EE中 218
4.3.3 如何消滅掉語句 220
4.3.3.1 通過錶達式消滅分支語句 221
4.3.3.2 通過函數遞歸消滅循環語句 222
4.3.3.3 其他可以被消滅的語句 223
4.4 函數:對運算式語言的補充和組織 224
4.4.1 函數是必要的補充 224
4.4.2 函數是代碼的組織形式 226
4.4.3 重新認識“函數” 227
4.4.3.1 “函數”==“lambda” 228
4.4.3.2 當運算符等義於某個函數時 228
4.4.4 JavaScript語言中的函數式編程 230
4.5 JavaScript中的函數 231
4.5.1 可變參數與值參數傳遞 231
4.5.2 非惰性求值 235
4.5.3 函數是第一型 237
4.5.4 函數是一個值 239
4.5.5 可遍曆的調用棧 239
4.5.5.1 callee:我是誰 240
4.5.5.2 caller:誰呼(叫)我 242
4.6 閉包 244
4.6.1 閉包與函數實例 244
4.6.1.1 什麼是閉包 245
4.6.1.2 什麼是函數實例與函數引用 246
4.6.1.3 (在被調用時,)每個函數實例至少擁有一個閉包 248
4.6.2 閉包與調用對象 250
4.6.2.1 “調用對象”的局部變量維護規則 252
4.6.2.2 “全局對象”的變量維護規則 252
4.6.2.3 函數閉包與“調用對象”的生存周期 253
4.6.3 閉包相關的一些特性 255
4.6.3.1 引用與泄漏 256
4.6.3.2 函數實例擁有多個閉包的情況 258
4.6.3.3 語句或語句塊中的閉包問題 260
4.6.3.4 閉包中的標識符(變量)特例 262
4.6.3.5 函數對象的閉包及其效果 265
4.6.4 閉包與可見性 266
4.6.4.1 函數閉包帶來的可見性效果 266
4.6.4.2 對象閉包帶來的可見性效果 269
4.6.4.3 匿名函數的閉包與可見性效果 273
4.7 【ES5】嚴格模式與閉包 274
4.7.1 嚴格模式下的執行限製 275
4.7.2 嚴格模式下的匿名函數遞歸問題 276
第5章 JavaScript的動態語言特性 279
5.1 概述 279
5.1.1 動態數據類型的起源 280
5.1.2 動態執行係統的起源 280
5.1.2.1 編譯係統、解釋係統與編碼 280
5.1.2.2 動態執行 281
5.1.3 腳本係統的起源 282
5.1.4 腳本隻是一種錶麵的錶現形式 283
5.2 動態執行 285
5.2.1 動態執行與閉包 285
5.2.1.1 eval使用全局閉包 286
5.2.1.2 eval使用當前函數的閉包 287
5.2.2 動態執行過程中的語句、錶達式與值 289
5.2.3 奇特的、甚至是負麵的影響 291
5.3 動態方法調用(call、apply與bind) 293
5.3.1 動態方法調用中指定this對象 293
5.3.2 丟失的this引用 295
5.3.3 棧的可見與修改 296
5.3.4 兼容性:低版本中的call()與apply() 298
5.3.5 【ES5】兼容性:ES5中的call()、apply() 301
5.3.6 【ES5】bind()方法與函數的延遲調用 302
5.4 重寫 303
5.4.1 原型重寫 304
5.4.2 構造器重寫 305
5.4.2.1 語法聲明與語句含義不一緻的問題 307
5.4.2.2 對象檢測的麻煩 310
5.4.2.3 構造器的原型(prototype屬性)不受重寫影響 311
5.4.2.4 “內部對象係統”不受影響 312
5.4.2.5 讓用戶對象係統影響內部對象係統 313
5.4.2.6 構造器重寫對直接量聲明的影響 314
5.4.2.7 構造綁定 315
5.4.2.8 內置構造器重寫的概述 317
5.4.3 對象成員的重寫 318
5.4.3.1 成員重寫的檢測 318
5.4.3.2 成員重寫的刪除 319
5.4.4 宿主對重寫的限製 321
5.4.5 引擎對重寫的限製 323
5.4.5.1 this的重寫 323
5.4.5.2 語句語法中的重寫 324
5.4.5.3 結構化異常處理中的重寫 326
5.5 包裝類:麵嚮對象的妥協 327
5.5.1 顯式包裝元數據 328
5.5.2 隱式包裝的過程與檢測方法 329
5.5.3 包裝值類型數據的必要性與問題 332
5.5.4 其他直接量與相應的構造器 333
5.5.4.1 函數特例 333
5.5.4.2 正則錶達式特例 334
5.6 關聯數組:對象與數組的動態特性 335
5.6.1 關聯數組是對象係統的基礎 336
5.6.2 用關聯數組實現的索引數組 336
5.6.3 乾淨的對象 339
5.7 類型轉換 342
5.7.1 宿主環境下的特殊類型係統 343
5.7.2 值運算:類型轉換的基礎 345
5.7.3 隱式轉換 346
5.7.3.1 運算導緻的類型轉換 346
5.7.3.2 語句(語義)導緻的類型轉換 348
5.7.4 值類型之間的轉換 348
5.7.4.1 undefined的轉換 349
5.7.4.2 number的轉換 349
5.7.4.3 boolean的轉換 350
5.7.4.4 string的轉換 351
5.7.4.5 值類型數據的顯式轉換 351
5.7.5 從引用到值:深入探究valueOf()方法 353
5.7.6 到字符串類型的顯式轉換 355
5.7.6.1 重寫toString()方法 356
5.7.6.2 從數值到字符串的顯式轉換 357
5.7.6.3 其他類型的顯式轉換 358
5.7.6.4 序列化 358
第3部分 編程實踐
第6章 元語言:QoBean核心技術與實現 363
6.1 QoBean語言層的基本特性 363
6.1.1 QoBean語言層概要 363
6.1.1.1 如何使用QoBean 364
6.1.1.2 QoBean中的麵嚮對象(OOP) 365
6.1.1.3 QoBean中的接口(Interface) 367
6.1.1.4 QoBean中的切麵(Aspect) 369
6.1.2 Qomo的體係結構及其與QoBean的關係 373
6.2 QoBean的元語言特性 374
6.2.1 QoBean如何理解元語言 374
6.2.2 算法與數據結構 375
6.2.2.1 引用類型與值類型的數據 376
6.2.2.2 函數調用 376
6.2.2.3 源起 377
6.2.2.4 小結 377
6.2.3 代碼組織形式 379
6.2.3.1 塊,以及基於塊的編織 379
6.2.3.2 更強的編織 381
6.2.3.3 邏輯代碼塊:局部、全局,以及閉包 382
6.2.3.4 邏輯的屬主 384
6.2.4 對“如何組織對象”的補充 385
6.2.4.1 原子,與原子聯結的友類、友函數 386
6.2.4.2 對象唯一化 387
6.2.5 綜述 390
6.3 基於元語言實現的語言特性 391
6.3.1 基於元語言的類繼承框架 391
6.3.1.1 類注冊過程 392
6.3.1.2 示例:實現MetaClass與MetaObject的約定 393
6.3.1.3 完整的Qomo語法實現 396
6.3.1.4 類類型樹的建立 400
6.3.2 多投事件 401
6.3.3 其他語言特性的實現 403
6.4 基於元語言實現的DSL 405
6.4.1 DSL的基本設計 405
6.4.2 DSL的基本實現 406
6.4.3 DSL的基本應用 409
6.4.4 一些修補 410
6.4.5 基於嚴格模式的一些修補 412
第7章 一般性的動態函數式語言技巧 415
7.1 消除代碼的全局變量名占用 415
7.2 一次性的構造器 417
7.3 對象充當識彆器 418
7.4 識彆new運算進行的構造器調用 420
7.5 使用直接量及其包裝類快速調用對象方法 421
7.6 三天前是星期幾 422
7.7 使用對象的值含義來構造復雜對象 423
7.8 控製字符串替換過程的基本模式 426
7.9 實現二叉樹 427
7.10 將函數封裝為方法 429
7.11 使用with語句來替代函數參數傳遞 431
7.12 使用對象閉包來重置重寫 432
7.13 構造函數參數 434
7.14 使用更復雜的錶達式來消減if語句 437
7.15 利用鈎子函數來擴展功能 439
7.16 安全的字符串 441
附錄A 術語錶 443
附錄B 主要引擎的特性差異列錶 447
附錄C 附圖 449
附錄D 參考書目 453
附錄E 本書各版次主要修改 455
· · · · · · (
收起)