ES6是下一代JavaScript語言標(biāo)準(zhǔn)的統(tǒng)稱,每年6月發(fā)布一次修訂版,迄今為止已經(jīng)發(fā)布了3個版本,分別是ES2015、ES2016、ES2017。本書根據(jù)ES2017標(biāo)準(zhǔn),詳盡介紹了所有新增的語法,對基本概念、設(shè)計目的和用法進行了清晰的講解,給出了大量簡單易懂的示例。本書為中級難度,適合那些已經(jīng)對JavaScript語言有一定了解的讀者,可以作為學(xué)習(xí)這門語言*進展的工具書,也可以作為參考手冊供大家隨時查閱新語法。第3版增加了超過30%的內(nèi)容,完全覆蓋了ES2017標(biāo)準(zhǔn),相比第2版介紹了更多的語法點,還調(diào)整了原有章節(jié)的文字表達,充實了示例,論述更準(zhǔn)確,更易懂易學(xué)。
橫跨ES2015/2016/2017新標(biāo),搶占JavaScript制高點
由千萬級名博、布道引領(lǐng)無數(shù)前端入行的阮一峰執(zhí)筆
來自BAT一線實踐,精彩案例透徹解讀新標(biāo)|保留語法
新標(biāo)首著,凝結(jié)多年研究心得,剖析ES理解應(yīng)用難題
第3版前言
4年前,當(dāng)我開始寫這本書的時候,ECMAScript
5.1版剛剛開始普及,最流行的框架還是jQuery。ES6看上去就像一個遙遠的藍圖,無人知道何時會實現(xiàn)。
僅僅4年,ES6已經(jīng)經(jīng)歷了ES2015、ES2016、ES2017這3個版本的迭代,各種實現(xiàn)的支持度已經(jīng)超過90%,不僅可以實現(xiàn)網(wǎng)頁的編寫,還可以實現(xiàn)服務(wù)器腳本、手機App和桌面應(yīng)用的編寫。程序員們完全接受了這個標(biāo)準(zhǔn),甚至大量使用尚未標(biāo)準(zhǔn)化的新語法。JavaScript語言就像一列高鐵,以令人眩暈的速度向前沖刺。
互聯(lián)網(wǎng)行業(yè)的蓬勃興旺造就了ES6的成功,也使得這本教程不斷更新,越寫越厚。第2版問世18個月之后,不得不推出第3版。
第3版新增了超過30%的內(nèi)容,完全覆蓋了ES2017標(biāo)準(zhǔn)(第2版只做到覆蓋 ES2015標(biāo)準(zhǔn)),并且對所有章節(jié)都進行了修訂,文字表達更準(zhǔn)確易懂,示例更豐富。對讀者來說,這個版本更容易學(xué)習(xí),更有參考價值。
這4年來,我對ES6的理解和所有的學(xué)習(xí)筆記,都濃縮在這本教程里面。那些我自己感到最困難的地方,書中都做出了詳細講解,給出了細致的示例,我相信這也是其他國內(nèi)學(xué)習(xí)者所需要的。
這本教程當(dāng)然也包含了些許局限,以及細致檢查之后仍然疏漏的各種錯誤。一旦發(fā)現(xiàn),我會第一時間更正。讀者可以到官方倉庫github.com/ruanyf/es6tutorial中查看勘誤。
我在微博上曾經(jīng)說過一段話,就把它放在這里作為結(jié)束吧。
我水平其實不高,只是好奇心重,從沒想到這么多人會關(guān)注。希望不要讓大家失望,未來做一塊墊腳石,為需要的朋友提供幫助,為技術(shù)的推廣和發(fā)展做出力所能及的貢獻。
阮一峰
2017年8月1日,寫于杭州
第1版前言
2012年年底,我開始動手做一個開源項目《JavaScript標(biāo)準(zhǔn)參考教程》(github.com/ruanyf/
jstutorial)。原來的設(shè)想是將自己的學(xué)習(xí)筆記整理成一本書,哪里料到,這個項目不斷膨脹,最后變成了ECMAScript 5及其外圍API的全面解讀和參考手冊,寫了一年多還沒寫完。
那個項目的最后一章就是ECMAScript 6的語法簡介。那一章也是越寫越長,最后我不得不決定,把它獨立出來,作為一個新項目,也就是您現(xiàn)在看到的這本書。
JavaScript已經(jīng)是互聯(lián)網(wǎng)開發(fā)的第一大語言,而且正在變成一種全領(lǐng)域的語言。著名程序員Jeff Atwood甚至提出了一條Atwood定律:所有可以用JavaScript編寫的程序,最終都會出現(xiàn)JavaScript的版本。(Any application that can be written in JavaScript will eventually be
written in JavaScript.)
ECMAScript正是JavaScript的國際標(biāo)準(zhǔn),這就決定了該標(biāo)準(zhǔn)的重要性。而ECMAScript 6是ECMAScript歷史上最大的一次版本升級,在語言的各個方面都有極大的變化,即使是熟練的JavaScript程序員,也需要重新學(xué)習(xí)。由于ES6的設(shè)計目標(biāo)是企業(yè)級開發(fā)和大型項目,所以可以預(yù)料,除了互聯(lián)網(wǎng)開發(fā)者,將來還會有大量應(yīng)用程序開發(fā)者(甚至操作系統(tǒng)開發(fā)者)成為ES6的學(xué)習(xí)者。
我寫作這本書的目標(biāo),就是想為上面這些學(xué)習(xí)者提供一本篇幅較短、簡明易懂、符合中文表達習(xí)慣的ES6教程。它由淺入深、循序漸進,既有重要概念的講解,又有API接口的羅列,便于日后當(dāng)作參考手冊查閱,還提供大量示例代碼,讓讀者不僅一看就懂,還能舉一反三,直接復(fù)制用于實際項目之中。
需要聲明的是,為了突出重點,本書只涉及ES6與ES5的不同之處,不對JavaScript已有的語法進行全面講解,畢竟市面上這樣的教程已經(jīng)有很多了。因此,本書不是JavaScript入門教材,不適合初學(xué)者。閱讀本書之前,需要對JavaScript的基本語法有所了解。
我本人也是一個ES6的學(xué)習(xí)者,不敢說自己有多高的水平,只是較早地接觸了這個主題,持續(xù)地讀了許多資料,追蹤標(biāo)準(zhǔn)的進展,做了詳細的筆記而已。雖然我盡了最大努力,并且原稿在GitHub上公開后已經(jīng)得到了大量的勘誤,但是本書的不盡如人意之處恐怕還有不少。
歡迎大家訪問本書的項目主頁(github.com/ruanyf/es6tutorial),提出意見,提交pull request。這些都會包括在本書的下一個版本中。
阮一峰
2014年6月4日,寫于上海
阮一峰,資深JavaScript 語言專家,知名技術(shù)博客作者,專注于網(wǎng)站開發(fā)技術(shù)十余年。暢銷書《黑客與畫家》、《軟件隨想錄》的譯者,現(xiàn)就職于螞蟻金服集團。
目錄
第1章 ECMAScript 6簡介1
1.1 ECMAScript和JavaScript的關(guān)系1
1.2 ES6與ECMAScript 2015的關(guān)系1
1.3 語法提案的批準(zhǔn)流程2
1.4 ECMAScript的歷史3
1.5 部署進度4
1.6 Babel 轉(zhuǎn)碼器4
1.6.1 配置文件.babelrc5
1.6.2 命令行轉(zhuǎn)碼babel-cli6
1.6.3 babel-node7
1.6.4 babel-register8
1.6.5 babel-core8
1.6.6 babel-polyfill9
1.6.7 瀏覽器環(huán)境10
1.6.8 在線轉(zhuǎn)換10
1.6.9 與其他工具的配合11
1.7 Traceur轉(zhuǎn)碼器11
1.7.1 直接插入網(wǎng)頁12
1.7.2 在線轉(zhuǎn)換13
1.7.3 命令行轉(zhuǎn)換14
1.7.4 Node環(huán)境的用法15
第2章 let和const命令17
2.1 let 命令17
2.1.1 基本用法17
2.1.2 不存在變量提升19
2.1.3 暫時性死區(qū)19
2.1.4 不允許重復(fù)聲明21
2.2 塊級作用域22
2.2.1 為什么需要塊級作用域22
2.2.2 ES6的塊級作用域23
2.2.3 塊級作用域與函數(shù)聲明24
2.2.4 do表達式27
2.3 const命令28
2.3.1 基本用法28
2.3.2 本質(zhì)29
2.3.3 ES6聲明變量的6種方法30
2.4 頂層對象的屬性30
2.5 global對象31
第3章 變量的解構(gòu)賦值33
3.1 數(shù)組的解構(gòu)賦值33
3.1.1 基本用法33
3.1.2 默認(rèn)值35
3.2 對象的解構(gòu)賦值37
3.3 字符串的解構(gòu)賦值41
3.4 數(shù)值和布爾值的解構(gòu)賦值41
3.5 函數(shù)參數(shù)的解構(gòu)賦值42
3.6 圓括號問題43
3.6.1 不能使用圓括號的情況43
3.6.2 可以使用圓括號的情況44
3.7 用途44
第4章 字符串的擴展49
4.1 字符的Unicode表示法49
4.2 codePointAt()50
4.3 String.fromCodePoint()52
4.4 字符串的遍歷器接口52
4.5 at()53
4.6 normalize()53
4.7 includes()、startsWith()、endsWith()54
4.8 repeat()55
4.9 padStart()、padEnd()56
4.10 模板字符串57
4.11 實例:模板編譯60
4.12 標(biāo)簽?zāi)0?2
4.13 String.raw()67
4.14 模板字符串的限制68
第5章 正則的擴展71
5.1 RegExp構(gòu)造函數(shù)71
5.2 字符串的正則方法72
5.3 u修飾符72
5.4 y修飾符74
5.5 sticky屬性77
5.6 flags屬性77
5.7 s修飾符:dotAll模式78
5.8 后行斷言79
5.9 Unicode屬性類80
5.10 具名組匹配81
5.10.1 簡介81
5.10.2 解構(gòu)賦值和替換82
5.10.3 引用83
第6章 數(shù)值的擴展85
6.1 二進制和八進制表示法85
6.2 Number.isFinite()、Number.isNaN()86
6.3 Number.parseInt()、Number.parseFloat()87
6.4 Number.isInteger()88
6.5 Number.EPSILON88
6.6 安全整數(shù)和Number.isSafeInteger()89
6.7 Math對象的擴展92
6.7.1 Math.trunc()92
6.7.2 Math.sign()92
6.7.3 Math.cbrt()93
6.7.4 Math.clz32()94
6.7.5 Math.imul()95
6.7.6 Math.fround()95
6.7.7 Math.hypot()96
6.7.8 對數(shù)方法96
6.7.9 雙曲函數(shù)方法98
6.8 Math.signbit()98
6.9 指數(shù)運算符99
6.10 Integer數(shù)據(jù)類型99
6.10.1 簡介99
6.10.2 運算100
第7章 函數(shù)的擴展103
7.1 函數(shù)參數(shù)的默認(rèn)值103
7.1.1 基本用法103
7.1.2 與解構(gòu)賦值默認(rèn)值結(jié)合使用105
7.1.3 參數(shù)默認(rèn)值的位置107
7.1.4 函數(shù)的length屬性108
7.1.5 作用域108
7.1.6 應(yīng)用111
7.2 rest參數(shù)112
7.3 嚴(yán)格模式113
7.4 name屬性115
7.5 箭頭函數(shù)116
7.5.1 基本用法116
7.5.2 注意事項118
7.5.3 嵌套的箭頭函數(shù)121
7.6 綁定this123
7.7 尾調(diào)用優(yōu)化124
7.7.1 什么是尾調(diào)用124
7.7.2 尾調(diào)用優(yōu)化125
7.7.3 尾遞歸126
7.7.4 遞歸函數(shù)的改寫128
7.7.5 嚴(yán)格模式129
7.7.6 尾遞歸優(yōu)化的實現(xiàn)129
7.8 函數(shù)參數(shù)的尾逗號132
第8章 數(shù)組的擴展133
8.1 擴展運算符133
8.1.1 含義133
8.1.2 替代數(shù)組的apply方法134
8.1.3 擴展運算符的應(yīng)用136
8.2 Array.from()139
8.3 Array.of()142
8.4 數(shù)組實例的copyWithin()143
8.5 數(shù)組實例的find()和findIndex()144
8.6 數(shù)組實例的fill()145
8.7 數(shù)組實例的entries()、keys()和values()145
8.8 數(shù)組實例的includes()146
8.9 數(shù)組的空位147
第9章 對象的擴展151
9.1 屬性的簡潔表示法151
9.2 屬性名表達式154
9.3 方法的name屬性156
9.4 Object.is()157
9.5 Object.assign()158
9.5.1 基本用法158
9.5.2 注意點160
9.5.3 常見用途161
9.6 屬性的可枚舉性163
9.7 屬性的遍歷165
9.8 __proto__ 屬性、Object.setPrototypeOf()、Object.getPrototypeOf()166
9.8.1 __proto__ 屬性166
9.8.2 Object.setPrototypeOf()167
9.8.3 Object.getPrototypeOf()168
9.9 Object.keys()、Object.values()、Object.entries()169
9.9.1 Object.keys()169
9.9.2 Object.values()170
9.9.3 Object.entries171
9.10 對象的擴展運算符173
9.11 Object.getOwnPropertyDescriptors()177
9.12 Null傳導(dǎo)運算符181
第10章 Symbol183
10.1 概述183
10.2 作為屬性名的Symbol185
10.3 實例:消除魔術(shù)字符串188
10.4 屬性名的遍歷189
10.5 Symbol.for()、Symbol.keyFor()191
10.6 實例:模塊的Singleton模式192
10.7 內(nèi)置的Symbol值194
10.7.1 Symbol.hasInstance194
10.7.2 Symbol.isConcatSpreadable195
10.7.3 Symbol.species196
10.7.4 Symbol.match197
10.7.5 Symbol.replace197
10.7.6 Symbol.search198
10.7.7 Symbol.split198
10.7.8 Symbol.iterator199
10.7.9 Symbol.toPrimitive200
10.7.10 Symbol.toStringTag201
10.7.11 Symbol.unscopables202
第11章 Set和Map數(shù)據(jù)結(jié)構(gòu)205
11.1 Set205
11.1.1 基本用法205
11.1.2 Set實例的屬性和方法207
11.1.3 遍歷操作208
11.2 WeakSet212
11.2.1 含義212
11.2.2 語法212
11.3 Map214
11.3.1 含義和基本用法214
11.3.2 實例的屬性和操作方法218
11.3.3 遍歷方法220
11.3.4 與其他數(shù)據(jù)結(jié)構(gòu)的互相轉(zhuǎn)換222
11.4 WeakMap225
11.4.1 含義225
11.4.2 WeakMap的語法227
11.4.3 WeakMap示例228
11.4.4 WeakMap的用途229
第12章 Proxy233
12.1 概述233
12.2 Proxy實例的方法237
12.2.1 get()237
12.2.2 set()241
12.2.3 apply()243
12.2.4 has()244
12.2.5 construct()246
12.2.6 deleteProperty()247
12.2.7 defineProperty()248
12.2.8 getOwnPropertyDescriptor()248
12.2.9 getPrototypeOf()249
12.2.10 isExtensible()249
12.2.11 ownKeys()250
12.2.12 preventExtensions()254
12.2.13 setPrototypeOf()255
12.3 Proxy.revocable()255
12.4 this問題256
12.5 實例:Web服務(wù)的客戶端258
第13章 Reflect259
13.1 概述259
13.2 靜態(tài)方法261
13.2.1 Reflect.get(target, name, receiver)262
13.2.2 Reflect.set(target, name, value, receiver)263
13.2.3 Reflect.has(obj, name)264
13.2.4 Reflect.deleteProperty(obj, name)265
13.2.5 Reflect.construct(target, args)265
13.2.6 Reflect.getPrototypeOf(obj)265
13.2.7 Reflect.setPrototypeOf(obj, newProto)266
13.2.8 Reflect.apply(func, thisArg, args)267
13.2.9 Reflect.defineProperty(target, propertyKey, attributes)267
13.2.10 Reflect.getOwnPropertyDescriptor (target, propertyKey)268
13.2.11 Reflect.isExtensible (target)268
13.2.12 Reflect.preventExtensions(target)269
13.2.13 Reflect.ownKeys (target)269
13.3 實例:使用Proxy實現(xiàn)觀察者模式270
第14章 Promise對象273
14.1 Promise的含義273
14.2 基本用法274
14.3 Promise.prototype.then()278
14.4 Promise.prototype.catch()279
14.5 Promise.all()285
14.6 Promise.race()287
14.7 Promise.resolve()288
14.8 Promise.reject()290
14.9 兩個有用的附加方法291
14.9.1 done()291
14.9.2 finally()292
14.10 應(yīng)用292
14.10.1 加載圖片292
14.10.2 Generator函數(shù)與Promise的結(jié)合293
14.11 Promise.try()294
第15章 Iterator和for...of循環(huán)297
15.1 Iterator(遍歷器)的概念297
15.2 默認(rèn)Iterator接口300
15.3 調(diào)用Iterator接口的場合305
15.4 字符串的Iterator接口307
15.5 Iterator接口與Generator函數(shù)308
15.6 遍歷器對象的return()、throw()309
15.7 for...of循環(huán)310
15.7.1 數(shù)組310
15.7.2 Set和Map結(jié)構(gòu)311
15.7.3 計算生成的數(shù)據(jù)結(jié)構(gòu)312
15.7.4 類似數(shù)組的對象313
15.7.5 對象314
15.7.6 與其他遍歷語法的比較315
第16章 Generator函數(shù)的語法317
16.1 簡介317
16.1.1 基本概念317
16.1.2 yield表達式319
16.1.3 與Iterator接口的關(guān)系322
16.2 next方法的參數(shù)323
16.3 for...of循環(huán)325
16.4 Generator.prototype.throw()328
16.5 Generator.prototype.return()334
16.6 yield*表達式335
16.7 作為對象屬1