ES6是下一代JavaScript語(yǔ)言標(biāo)準(zhǔn)的統(tǒng)稱(chēng),每年6月發(fā)布一次修訂版,迄今為止已經(jīng)發(fā)布了3個(gè)版本,分別是ES2015、ES2016、ES2017。本書(shū)根據(jù)ES2017標(biāo)準(zhǔn),詳盡介紹了所有新增的語(yǔ)法,對(duì)基本概念、設(shè)計(jì)目的和用法進(jìn)行了清晰的講解,給出了大量簡(jiǎn)單易懂的示例。本書(shū)為中級(jí)難度,適合那些已經(jīng)對(duì)JavaScript語(yǔ)言有一定了解的讀者,可以作為學(xué)習(xí)這門(mén)語(yǔ)言*進(jìn)展的工具書(shū),也可以作為參考手冊(cè)供大家隨時(shí)查閱新語(yǔ)法。第3版增加了超過(guò)30%的內(nèi)容,完全覆蓋了ES2017標(biāo)準(zhǔn),相比第2版介紹了更多的語(yǔ)法點(diǎn),還調(diào)整了原有章節(jié)的文字表達(dá),充實(shí)了示例,論述更準(zhǔn)確,更易懂易學(xué)。
橫跨ES2015/2016/2017新標(biāo),搶占JavaScript制高點(diǎn)
由千萬(wàn)級(jí)名博、布道引領(lǐng)無(wú)數(shù)前端入行的阮一峰執(zhí)筆
來(lái)自BAT一線實(shí)踐,精彩案例透徹解讀新標(biāo)|保留語(yǔ)法
新標(biāo)首著,凝結(jié)多年研究心得,剖析ES理解應(yīng)用難題
第3版前言
4年前,當(dāng)我開(kāi)始寫(xiě)這本書(shū)的時(shí)候,ECMAScript
5.1版剛剛開(kāi)始普及,最流行的框架還是jQuery。ES6看上去就像一個(gè)遙遠(yuǎn)的藍(lán)圖,無(wú)人知道何時(shí)會(huì)實(shí)現(xiàn)。
僅僅4年,ES6已經(jīng)經(jīng)歷了ES2015、ES2016、ES2017這3個(gè)版本的迭代,各種實(shí)現(xiàn)的支持度已經(jīng)超過(guò)90%,不僅可以實(shí)現(xiàn)網(wǎng)頁(yè)的編寫(xiě),還可以實(shí)現(xiàn)服務(wù)器腳本、手機(jī)App和桌面應(yīng)用的編寫(xiě)。程序員們完全接受了這個(gè)標(biāo)準(zhǔn),甚至大量使用尚未標(biāo)準(zhǔn)化的新語(yǔ)法。JavaScript語(yǔ)言就像一列高鐵,以令人眩暈的速度向前沖刺。
互聯(lián)網(wǎng)行業(yè)的蓬勃興旺造就了ES6的成功,也使得這本教程不斷更新,越寫(xiě)越厚。第2版問(wèn)世18個(gè)月之后,不得不推出第3版。
第3版新增了超過(guò)30%的內(nèi)容,完全覆蓋了ES2017標(biāo)準(zhǔn)(第2版只做到覆蓋 ES2015標(biāo)準(zhǔn)),并且對(duì)所有章節(jié)都進(jìn)行了修訂,文字表達(dá)更準(zhǔn)確易懂,示例更豐富。對(duì)讀者來(lái)說(shuō),這個(gè)版本更容易學(xué)習(xí),更有參考價(jià)值。
這4年來(lái),我對(duì)ES6的理解和所有的學(xué)習(xí)筆記,都濃縮在這本教程里面。那些我自己感到最困難的地方,書(shū)中都做出了詳細(xì)講解,給出了細(xì)致的示例,我相信這也是其他國(guó)內(nèi)學(xué)習(xí)者所需要的。
這本教程當(dāng)然也包含了些許局限,以及細(xì)致檢查之后仍然疏漏的各種錯(cuò)誤。一旦發(fā)現(xiàn),我會(huì)第一時(shí)間更正。讀者可以到官方倉(cāng)庫(kù)github.com/ruanyf/es6tutorial中查看勘誤。
我在微博上曾經(jīng)說(shuō)過(guò)一段話,就把它放在這里作為結(jié)束吧。
我水平其實(shí)不高,只是好奇心重,從沒(méi)想到這么多人會(huì)關(guān)注。希望不要讓大家失望,未來(lái)做一塊墊腳石,為需要的朋友提供幫助,為技術(shù)的推廣和發(fā)展做出力所能及的貢獻(xiàn)。
阮一峰
2017年8月1日,寫(xiě)于杭州
第1版前言
2012年年底,我開(kāi)始動(dòng)手做一個(gè)開(kāi)源項(xiàng)目《JavaScript標(biāo)準(zhǔn)參考教程》(github.com/ruanyf/
jstutorial)。原來(lái)的設(shè)想是將自己的學(xué)習(xí)筆記整理成一本書(shū),哪里料到,這個(gè)項(xiàng)目不斷膨脹,最后變成了ECMAScript 5及其外圍API的全面解讀和參考手冊(cè),寫(xiě)了一年多還沒(méi)寫(xiě)完。
那個(gè)項(xiàng)目的最后一章就是ECMAScript 6的語(yǔ)法簡(jiǎn)介。那一章也是越寫(xiě)越長(zhǎng),最后我不得不決定,把它獨(dú)立出來(lái),作為一個(gè)新項(xiàng)目,也就是您現(xiàn)在看到的這本書(shū)。
JavaScript已經(jīng)是互聯(lián)網(wǎng)開(kāi)發(fā)的第一大語(yǔ)言,而且正在變成一種全領(lǐng)域的語(yǔ)言。著名程序員Jeff Atwood甚至提出了一條Atwood定律:所有可以用JavaScript編寫(xiě)的程序,最終都會(huì)出現(xiàn)JavaScript的版本。(Any application that can be written in JavaScript will eventually be
written in JavaScript.)
ECMAScript正是JavaScript的國(guó)際標(biāo)準(zhǔn),這就決定了該標(biāo)準(zhǔn)的重要性。而ECMAScript 6是ECMAScript歷史上最大的一次版本升級(jí),在語(yǔ)言的各個(gè)方面都有極大的變化,即使是熟練的JavaScript程序員,也需要重新學(xué)習(xí)。由于ES6的設(shè)計(jì)目標(biāo)是企業(yè)級(jí)開(kāi)發(fā)和大型項(xiàng)目,所以可以預(yù)料,除了互聯(lián)網(wǎng)開(kāi)發(fā)者,將來(lái)還會(huì)有大量應(yīng)用程序開(kāi)發(fā)者(甚至操作系統(tǒng)開(kāi)發(fā)者)成為ES6的學(xué)習(xí)者。
我寫(xiě)作這本書(shū)的目標(biāo),就是想為上面這些學(xué)習(xí)者提供一本篇幅較短、簡(jiǎn)明易懂、符合中文表達(dá)習(xí)慣的ES6教程。它由淺入深、循序漸進(jìn),既有重要概念的講解,又有API接口的羅列,便于日后當(dāng)作參考手冊(cè)查閱,還提供大量示例代碼,讓讀者不僅一看就懂,還能舉一反三,直接復(fù)制用于實(shí)際項(xiàng)目之中。
需要聲明的是,為了突出重點(diǎn),本書(shū)只涉及ES6與ES5的不同之處,不對(duì)JavaScript已有的語(yǔ)法進(jìn)行全面講解,畢竟市面上這樣的教程已經(jīng)有很多了。因此,本書(shū)不是JavaScript入門(mén)教材,不適合初學(xué)者。閱讀本書(shū)之前,需要對(duì)JavaScript的基本語(yǔ)法有所了解。
我本人也是一個(gè)ES6的學(xué)習(xí)者,不敢說(shuō)自己有多高的水平,只是較早地接觸了這個(gè)主題,持續(xù)地讀了許多資料,追蹤標(biāo)準(zhǔn)的進(jìn)展,做了詳細(xì)的筆記而已。雖然我盡了最大努力,并且原稿在GitHub上公開(kāi)后已經(jīng)得到了大量的勘誤,但是本書(shū)的不盡如人意之處恐怕還有不少。
歡迎大家訪問(wèn)本書(shū)的項(xiàng)目主頁(yè)(github.com/ruanyf/es6tutorial),提出意見(jiàn),提交pull request。這些都會(huì)包括在本書(shū)的下一個(gè)版本中。
阮一峰
2014年6月4日,寫(xiě)于上海
阮一峰,資深JavaScript 語(yǔ)言專(zhuān)家,知名技術(shù)博客作者,專(zhuān)注于網(wǎng)站開(kāi)發(fā)技術(shù)十余年。暢銷(xiāo)書(shū)《黑客與畫(huà)家》、《軟件隨想錄》的譯者,現(xiàn)就職于螞蟻金服集團(tuán)。
目錄
第1章 ECMAScript 6簡(jiǎn)介1
1.1 ECMAScript和JavaScript的關(guān)系1
1.2 ES6與ECMAScript 2015的關(guān)系1
1.3 語(yǔ)法提案的批準(zhǔn)流程2
1.4 ECMAScript的歷史3
1.5 部署進(jìn)度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)頁(yè)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 暫時(shí)性死區(qū)19
2.1.4 不允許重復(fù)聲明21
2.2 塊級(jí)作用域22
2.2.1 為什么需要塊級(jí)作用域22
2.2.2 ES6的塊級(jí)作用域23
2.2.3 塊級(jí)作用域與函數(shù)聲明24
2.2.4 do表達(dá)式27
2.3 const命令28
2.3.1 基本用法28
2.3.2 本質(zhì)29
2.3.3 ES6聲明變量的6種方法30
2.4 頂層對(duì)象的屬性30
2.5 global對(duì)象31
第3章 變量的解構(gòu)賦值33
3.1 數(shù)組的解構(gòu)賦值33
3.1.1 基本用法33
3.1.2 默認(rèn)值35
3.2 對(duì)象的解構(gòu)賦值37
3.3 字符串的解構(gòu)賦值41
3.4 數(shù)值和布爾值的解構(gòu)賦值41
3.5 函數(shù)參數(shù)的解構(gòu)賦值42
3.6 圓括號(hào)問(wèn)題43
3.6.1 不能使用圓括號(hào)的情況43
3.6.2 可以使用圓括號(hào)的情況44
3.7 用途44
第4章 字符串的擴(kuò)展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 實(shí)例:模板編譯60
4.12 標(biāo)簽?zāi)0?2
4.13 String.raw()67
4.14 模板字符串的限制68
第5章 正則的擴(kuò)展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屬性類(lèi)80
5.10 具名組匹配81
5.10.1 簡(jiǎn)介81
5.10.2 解構(gòu)賦值和替換82
5.10.3 引用83
第6章 數(shù)值的擴(kuò)展85
6.1 二進(jìn)制和八進(jìn)制表示法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對(duì)象的擴(kuò)展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 對(duì)數(shù)方法96
6.7.9 雙曲函數(shù)方法98
6.8 Math.signbit()98
6.9 指數(shù)運(yùn)算符99
6.10 Integer數(shù)據(jù)類(lèi)型99
6.10.1 簡(jiǎn)介99
6.10.2 運(yùn)算100
第7章 函數(shù)的擴(kuò)展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 注意事項(xiàng)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ù)的改寫(xiě)128
7.7.5 嚴(yán)格模式129
7.7.6 尾遞歸優(yōu)化的實(shí)現(xiàn)129
7.8 函數(shù)參數(shù)的尾逗號(hào)132
第8章 數(shù)組的擴(kuò)展133
8.1 擴(kuò)展運(yùn)算符133
8.1.1 含義133
8.1.2 替代數(shù)組的apply方法134
8.1.3 擴(kuò)展運(yùn)算符的應(yīng)用136
8.2 Array.from()139
8.3 Array.of()142
8.4 數(shù)組實(shí)例的copyWithin()143
8.5 數(shù)組實(shí)例的find()和findIndex()144
8.6 數(shù)組實(shí)例的fill()145
8.7 數(shù)組實(shí)例的entries()、keys()和values()145
8.8 數(shù)組實(shí)例的includes()146
8.9 數(shù)組的空位147
第9章 對(duì)象的擴(kuò)展151
9.1 屬性的簡(jiǎn)潔表示法151
9.2 屬性名表達(dá)式154
9.3 方法的name屬性156
9.4 Object.is()157
9.5 Object.assign()158
9.5.1 基本用法158
9.5.2 注意點(diǎn)160
9.5.3 常見(jiàn)用途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 對(duì)象的擴(kuò)展運(yùn)算符173
9.11 Object.getOwnPropertyDescriptors()177
9.12 Null傳導(dǎo)運(yùn)算符181
第10章 Symbol183
10.1 概述183
10.2 作為屬性名的Symbol185
10.3 實(shí)例:消除魔術(shù)字符串188
10.4 屬性名的遍歷189
10.5 Symbol.for()、Symbol.keyFor()191
10.6 實(shí)例:模塊的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實(shí)例的屬性和方法207
11.1.3 遍歷操作208
11.2 WeakSet212
11.2.1 含義212
11.2.2 語(yǔ)法212
11.3 Map214
11.3.1 含義和基本用法214
11.3.2 實(shí)例的屬性和操作方法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的語(yǔ)法227
11.4.3 WeakMap示例228
11.4.4 WeakMap的用途229
第12章 Proxy233
12.1 概述233
12.2 Proxy實(shí)例的方法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問(wèn)題256
12.5 實(shí)例:Web服務(wù)的客戶(hù)端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 實(shí)例:使用Proxy實(shí)現(xiàn)觀察者模式270
第14章 Promise對(duì)象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 兩個(gè)有用的附加方法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接口的場(chǎng)合305
15.4 字符串的Iterator接口307
15.5 Iterator接口與Generator函數(shù)308
15.6 遍歷器對(duì)象的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 計(jì)算生成的數(shù)據(jù)結(jié)構(gòu)312
15.7.4 類(lèi)似數(shù)組的對(duì)象313
15.7.5 對(duì)象314
15.7.6 與其他遍歷語(yǔ)法的比較315
第16章 Generator函數(shù)的語(yǔ)法317
16.1 簡(jiǎn)介317
16.1.1 基本概念317
16.1.2 yield表達(dá)式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*表達(dá)式335
16.7 作為對(duì)象屬1