es2015是es6。es全稱“ECMAScript”,是根據(jù)ECMA-262標(biāo)準(zhǔn)實(shí)現(xiàn)的通用腳本語(yǔ)言,而由2015年6月正式發(fā)布的版本,其正式名為ECMAScript2015(ES2015),因其是ECMAScript的第6個(gè)版本,因此可簡(jiǎn)稱為es6。
前端(vue)入門到精通課程:進(jìn)入學(xué)習(xí)
Apipost = Postman + Swagger + Mock + Jmeter 超好用的API調(diào)試工具:點(diǎn)擊使用
本教程操作環(huán)境:windows7系統(tǒng)、ECMAScript 6版、Dell G3電腦。
“es”簡(jiǎn)介
es全稱“ECMAScript”,是根據(jù) ECMA-262 標(biāo)準(zhǔn)實(shí)現(xiàn)的通用腳本語(yǔ)言,ECMA-262 標(biāo)準(zhǔn)主要規(guī)定了這門語(yǔ)言的語(yǔ)法、類型、語(yǔ)句、關(guān)鍵字、保留字、操作符、對(duì)象等幾個(gè)部分。每次看到 ES 后面跟著數(shù)字,是 ECMAScript 的不同版本。
es6/ ES2015
es6全稱ECMAScript6(ECMAScript的第6個(gè)版本),是于2015年6月正式發(fā)布的JavaScript語(yǔ)言的標(biāo)準(zhǔn),正式名為ECMAScript 2015(ES2015)。它的目標(biāo)是使得JavaScript語(yǔ)言可以用來(lái)編寫復(fù)雜的大型應(yīng)用程序,成為企業(yè)級(jí)開發(fā)語(yǔ)言。
ECMAScript 6 目前基本成為業(yè)界標(biāo)準(zhǔn),它的普及速度比 ES5 要快很多,主要原因是現(xiàn)代瀏覽器對(duì) ES6 的支持相當(dāng)迅速,尤其是 Chrome 和 Firefox 瀏覽器,已經(jīng)支持 ES6 中絕大多數(shù)的特性。
在此后ECMA Script每年發(fā)布一個(gè)大版本新增加一些重要特性,我們稱之為ES6+。
本文主要總結(jié)了ES2015-ES2019的主要特性,一個(gè)學(xué)習(xí)前端的童鞋應(yīng)該是常用且理解的一些特性。
ES2015 的主要作用:
- 解決原有語(yǔ)法的一些不足
- 對(duì)原有語(yǔ)法進(jìn)行增強(qiáng)
- 全新的對(duì)象、全新的方法、全新的功能
Promise、Proxy、Object.assign等
- 全新的數(shù)據(jù)類型和數(shù)據(jù)結(jié)構(gòu)
Symbol、Set、Map等
ES2015 常用的環(huán)境支持情況
- nodejs查詢:https://node.green/
- 瀏覽器查詢:http://kangax.github.io/compat-table/es6/
PC瀏覽器對(duì)ES2015的支持情況
- Chrome:51 版起便可以支持 97% 的 ES6 新特性。
- Firefox:53 版起便可以支持 97% 的 ES6 新特性。
- Safari:10 版起便可以支持 99% 的 ES6 新特性。
- Edge:Edge 15可以支持 96% 的 ES6 新特性。Edge 14 可以支持 93% 的 ES6 新特性。
- IE:IE7 ~ 11 基本不支持 ES6
移動(dòng)端瀏覽器對(duì)ES2015的支持情況
- iOS:10.0 版起便可以支持 99% 的 ES6 新特性。
- Android:基本不支持 ES6 新特性(5.1 僅支持 25%)
服務(wù)器對(duì)ES2015的支持情況,具體查看:https://node.green/
- Node.js:6.5 版起便可以支持 97% 的 ES6 新特性。(6.0 支持 92%)
var(對(duì)比let、const)
- 只有全局作用域、函數(shù)作用域,不存在嚴(yán)格的塊級(jí)作用域
- 存在變量提升
- 變量的聲明和定義可以分開進(jìn)行
- 變量可以重復(fù)聲明
let(塊級(jí)作用域)
- 存在塊級(jí)作用域
- 不能變量提升
- 變量的聲明和定義可以分開進(jìn)行
- 變量不能重復(fù)聲明
const 常量
- 存在塊級(jí)作用域
- 不能變量提升
- 變量的聲明和定義必須在同一個(gè)語(yǔ)句中
- 變量不能重復(fù)聲明
- 不能修改聲明過(guò)的變量值(例如:可以修改對(duì)象的屬性值,不能修改對(duì)象地址)
- 最佳實(shí)踐:不用var,主用const,配合let
數(shù)組解構(gòu)
const [foo, bar, baz] = arr console.log(foo, bar, baz) const [, , baz] = arr console.log(baz) // 解構(gòu)剩余的數(shù)組元素 // 只能在最后一個(gè)位置使用擴(kuò)展運(yùn)算符 const [foo, ...rest] = arr console.log(rest) // 解構(gòu)時(shí)元素較少,按照順序取元素 const [foo] = arr console.log(foo) // 解構(gòu)時(shí)設(shè)置默認(rèn)值 const [foo, bar, baz = 123, more = 'default value'] = arr console.log(bar, more)
對(duì)象解構(gòu)
const obj = { name: 'zce', age: 18 } // 變量名重復(fù)時(shí),可以重命名和設(shè)置默認(rèn)值 const name = 'tom' const { name: objName = 'jack' } = obj console.log(objName)
模板字符串
- 支持換行符
- 支持嵌入變量、表達(dá)式
const name = 'tom' // 可以通過(guò) ${} 插入表達(dá)式,表達(dá)式的執(zhí)行結(jié)果將會(huì)輸出到對(duì)應(yīng)位置 const msg = `hey, ${name} --- ${1 + 2} ---- ${Math.random()}` console.log(msg)
字符串的擴(kuò)展方法
- includes 包含字符串
- startsWith 是否以某字符串開頭
- endsWith 是否以某字符串結(jié)束
const message = 'Error: foo is not defined.' console.log( // message.startsWith('Error') // message.endsWith('.') message.includes('foo') )
方法的參數(shù)默認(rèn)值
- 在function參數(shù)后面使用=設(shè)置默認(rèn)值
- 只有當(dāng)形參傳遞是undefined或者沒(méi)有傳遞值時(shí),才會(huì)設(shè)置默認(rèn)值(false也不會(huì))
- 如果只有部分默認(rèn)值,需要將設(shè)置默認(rèn)值的代碼放到后面;否則無(wú)法正常使用
// 默認(rèn)參數(shù)一定是在形參列表的最后 function foo (bar,enable = true) { console.log('foo invoked - enable: ') console.log(enable) } foo(false)
方法的剩余參數(shù)
- 只能出現(xiàn)在形參的最后一位
- 只能使用一次
- args是一個(gè)數(shù)組,區(qū)別于arguments是一個(gè)偽數(shù)組
function foo (first, ...args) { console.log(args) } foo(1, 2, 3, 4)
展開數(shù)組
const arr = ['foo', 'bar', 'baz'] // console.log( // arr[0], // arr[1], // arr[2], // ) // console.log.apply(console, arr) console.log(...arr)
箭頭函數(shù)
插件:Fira Code字體將箭頭畫的更好看
const arr = [1, 2, 3, 4, 5, 6, 7] // arr.filter(function (item) { // return item % 2 // }) // 常用場(chǎng)景,回調(diào)函數(shù) arr.filter(i => i % 2)
箭頭函數(shù)的簡(jiǎn)寫
function(value){return value} 等價(jià)于 value=>value
箭頭函數(shù)的this指向
- 普通函數(shù)的this指向調(diào)用它方法的對(duì)象
- 箭頭函數(shù)的this和它外面函數(shù)的this指向相同,即:箭頭函數(shù)不會(huì)改變this的指向
// 箭頭函數(shù)與 this // 箭頭函數(shù)不會(huì)改變 this 指向 const person = { name: 'tom', // sayHi: function () { // console.log(`hi, my name is ${this.name}`)//tom,this指向該函數(shù)調(diào)用者 // } sayHi: () => { console.log(`hi, my name is ${this.name}`) //undefined,this和sayHi()外面的函數(shù)this相同 }, sayHiAsync: function () { // const _this = this // setTimeout(function () { // console.log(_this.name) //這里的this為window,所以需要使用_this // }, 1000) console.log(this) setTimeout(() => { // console.log(this.name) //這里的this指向sayHiAsync里的this,即person console.log(this) }, 1000) } } person.sayHi() person.sayHiAsync()
對(duì)象字面量
- 如果屬性名和值的變量名相同,可以省略一個(gè)變量
- 方法的簡(jiǎn)寫:可以省略“:function”
- 計(jì)算屬性名:屬性名可以在[]里面使用任意表達(dá)式
const bar = '345' const obj = { foo: 123, // bar: bar // 屬性名與變量名相同,可以省略 : bar bar, // method1: function () { // console.log('method111') // } // 方法可以省略 : function method1 () { console.log('method111') // 這種方法就是普通的函數(shù),this 指向obj。 console.log(this) }, // Math.random(): 123 // 不允許,使用[]才行 // 通過(guò) [] 讓表達(dá)式的結(jié)果作為屬性名 [bar]: 123 }
Object.assign
Object.assign是不完全的深拷貝?它究竟拷貝了多少東西?
獲取不到obj中的get、set信息
- 將源對(duì)象中的值賦值到目標(biāo)對(duì)象
- 目標(biāo)對(duì)象和返回值是同一個(gè)對(duì)象
- 如果目標(biāo)對(duì)象中有相同名字的屬性,則覆蓋該屬性
- 可以傳入多個(gè)源對(duì)象,按照順序依次覆蓋目標(biāo)對(duì)象
const source1 = { a: 123, b: 123 } const source2 = { b: 789, d: 789 } const target = { a: 456, c: 456 } const result = Object.assign(target, source1, source2) console.log(target) console.log(result === target) //true,目標(biāo)對(duì)象和返回值是一個(gè)對(duì)象
Object.is
0 == false // => true 0 === false // => false +0 === -0 // => true NaN === NaN // => false Object.is(+0, -0) // => false Object.is(NaN, NaN) // => true
Proxy 和 Object.defineProperty
Proxy的作用
對(duì)Object屬性變化進(jìn)行監(jiān)聽(tīng)
對(duì)比Object.defineProperty
參考筆記:https://gitee.com/ymcdhr/e-task/wikis/?sort_id=4053906
Reflect(統(tǒng)一的操作Object對(duì)象方法)
- Proxy屬性的方法中默認(rèn)調(diào)用了Reflect中的方法,例如:
const obj = { foo: '123', bar: '456' } const proxy = new Proxy(obj, { get (target, property) { console.log('watch logic~') // Proxy中如果不寫,默認(rèn)調(diào)用了此方法 return Reflect.get(target, property) } })
- Relect提供了統(tǒng)一的操作Object對(duì)象的方法,MDN上有完整的13中方法:
https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Reflect
// console.log('name' in obj) // console.log(delete obj['age']) // console.log(Object.keys(obj)) console.log(Reflect.has(obj, 'name')) console.log(Reflect.deleteProperty(obj, 'age')) console.log(Reflect.ownKeys(obj))
Promise
Class 類的基本語(yǔ)法
// class 關(guān)鍵詞 // function Person (name) { // this.name = name // } // Person.prototype.say = function () { // console.log(`hi, my name is ${this.name}`) // } class Person { // 構(gòu)造函數(shù) constructor (name) { this.name = name } // 成員變量 age = 18 // 成員函數(shù) say () { console.log(`hi, my name is ${this.name}`) } } const p = new Person('tom') p.say()
Class 中的靜態(tài)方法static
- 聲明靜態(tài)方法:static關(guān)鍵字
- 調(diào)用靜態(tài)方法:Person.say
- 靜態(tài)方法的this指向?yàn)轭?/li>
// static 方法 class Person { constructor (name) { this.name = name } say () { console.log(`hi, my name is ${this.name}`) } static create (name) { return new Person(name) } } const tom = Person.create('tom') tom.say()
Class 的繼承
- 使用extends繼承
- 注意super的使用,能夠訪問(wèn)父類;通常用來(lái)執(zhí)行父類構(gòu)造函數(shù)。
class Person { constructor (name) { this.name = name } say () { console.log(`hi, my name is ${this.name}`) } } class Student extends Person { constructor (name, number) { super(name) // 調(diào)用父類構(gòu)造函數(shù),否則name就沒(méi)有賦值(重要) this.number = number } hello () { super.say() // 調(diào)用父類成員 console.log(`my school number is ${this.number}`) } } const s = new Student('jack', '100') s.hello()
Set、Map
Set 沒(méi)有重復(fù)元素的數(shù)組集合
常用的成員方法
- s.add(item) 添加item,返回集合本身,可鏈?zhǔn)秸{(diào)用
- s.size 獲取Set的長(zhǎng)度
- s.has(item)判斷是否存在某個(gè)item
- s.delete(item)刪除某個(gè)item
- s.clear()刪除全部
const s = new Set() s.add(1).add(2).add(3).add(4).add(2) // console.log(s) // s.forEach(i => console.log(i)) //forEach、for...of 都可以用來(lái)遍歷Set // for (let i of s) { // console.log(i) // } // console.log(s.size) // console.log(s.has(100)) // console.log(s.delete(3)) // console.log(s) // s.clear() // console.log(s)
常用來(lái)數(shù)組去重
// 應(yīng)用場(chǎng)景:數(shù)組去重 const arr = [1, 2, 1, 3, 4, 1] const result1 = Array.from(new Set(arr)) const result2 = [...new Set(arr)] console.log(result1,result2)
Map 能使用復(fù)雜結(jié)構(gòu)作為屬性的對(duì)象集合
以前的對(duì)象存儲(chǔ)對(duì)象屬性時(shí),會(huì)將復(fù)雜數(shù)據(jù)轉(zhuǎn)換成字符串(toString()方法),如下:
const obj = {} obj[true] = 'value' obj[123] = 'value' obj[{ a: 1 }] = 'value' console.log(Object.keys(obj)) //0: "123" //1: "true" //2: "[object Object]"
使用Map可以存儲(chǔ)復(fù)雜數(shù)據(jù)作為對(duì)象屬性,常用的方法有如下:
const m = new Map() const tom = { name: 'tom' } m.set(tom, 90) console.log(m) console.log(m.get(tom)) // m.has() // m.delete() // m.clear() // forEach可以遍歷Map中的item m.forEach((value, key) => { console.log(value, key) })
Symbol
一個(gè)全新的基礎(chǔ)數(shù)據(jù)類型,每次創(chuàng)建都是獨(dú)一無(wú)二的值
let s = Symbol(); typeof s // "symbol" let s1 = Symbol('foo'); let s2 = Symbol('foo'); s1 === s2 // false // for方法是創(chuàng)建的一樣的值,參數(shù)會(huì)自動(dòng)轉(zhuǎn)換成字符串 let s3 = Symbol.for('foo'); let s4 = Symbol.for('foo'); s3 === s4 // true
可以轉(zhuǎn)換為字符串,通過(guò)description(ES2019提供的方法)
let s1 = Symbol('foo'); let s2 = Symbol('foo'); s1 // Symbol(foo) s2 // Symbol(foo) s1 === s2 // false s1.toString() // "Symbol(foo)" s2.toString() // "Symbol(foo)" s1.description // "foo" // ES2019提供的方法
可以作為對(duì)象的屬性名,可以避免同名沖突
const obj = {} obj[Symbol()] = '123' obj[Symbol()] = '456' console.log(obj) //Symbol(): "123" //Symbol(): "456"
使用 Symbol 值定義屬性時(shí),Symbol 值必須放在方括號(hào)之中,而且不能使用點(diǎn)運(yùn)算符
let s = Symbol(); // 第一種寫法 let a = {}; a[s] = 'Hello!'; // 第二種寫法 let a = { [s]: 'Hello!' }; // 以上寫法都得到同樣結(jié)果 a[s] // "Hello!"
可以作為對(duì)象的私有成員,不能在外部直接訪問(wèn)(因?yàn)槊看卧L問(wèn)都不一樣),只能通過(guò)內(nèi)部this訪問(wèn)
// 案例2:Symbol 模擬實(shí)現(xiàn)私有成員 // a.js ====================================== const name = Symbol() const person = { [name]: 'zce', say () { console.log(this[name]) } } // 只對(duì)外暴露 person // b.js ======================================= // 由于無(wú)法創(chuàng)建出一樣的 Symbol 值, // 所以無(wú)法直接訪問(wèn)到 person 中的「私有」成員 // person[Symbol()] person.say()
注意:for…in、Obeject.keys、Json.stringify都無(wú)法在Symbol上使用
使用:Object.getOwnPropertySymbols,替代Obeject.keys方法用于Symbol
for…of 統(tǒng)一遍歷方法
以前的 for…in 遍歷鍵值對(duì),forEach 存在局限性
-
可以用使用break終止遍歷,forEach不能跳出循環(huán)
-
可以遍歷Array數(shù)組、Set和Map對(duì)象
-
普通對(duì)象不能被直接 for…of 遍歷,因?yàn)樗鼪](méi)有Symbol.iterator屬性
對(duì)象(Object)之所以沒(méi)有默認(rèn)部署 Iterator 接口,是因?yàn)閷?duì)象的哪個(gè)屬性先遍歷,哪個(gè)屬性后遍歷是不確定的,需要開發(fā)者手動(dòng)指定。
-
所有可以使用 for…of 的對(duì)象都需要具有Symbol.iterator屬性
// for...of 循環(huán) const arr = [100, 200, 300, 400] // for...of 循環(huán)可以替代 數(shù)組對(duì)象的 forEach 方法 但可以使用break跳出循環(huán) arr.forEach(item => { console.log(item) }) for (const item of arr) { console.log(item) if (item > 100) { break } } // forEach 無(wú)法跳出循環(huán),必須使用 some 或者 every 方法 // arr.forEach() // 不能跳出循環(huán) // arr.some() // arr.every() // 遍歷 Set 與遍歷數(shù)組相同 const s = new Set(['foo', 'bar']) for (const item of s) { console.log(item) } // 遍歷 Map 可以配合數(shù)組結(jié)構(gòu)語(yǔ)法,直接獲取鍵值 const m = new Map() m.set('foo', '123') m.set('bar', '345') for (const [key, value] of m) { console.log(key, value) } // 普通對(duì)象不能被直接 for...of 遍歷 const obj = { foo: 123, bar: 456 } for (const item of obj) { console.log(item) }
可迭代接口 iterator(主要給for…of使用)
- 一些數(shù)據(jù)結(jié)構(gòu)的原型對(duì)象 _ proto _ 中含有Symbol.iterator方法
- iterator方法返回一個(gè)帶next()方法的指針對(duì)象
- 每次執(zhí)行next()方法,它都會(huì)返回下一個(gè)數(shù)據(jù)
具有 Symbol.iterator 屬性的數(shù)據(jù)結(jié)構(gòu)
Array、Map、Set、String、TypedArray、函數(shù)的 arguments 對(duì)象、NodeList 對(duì)象
iterator 的遍歷過(guò)程是這樣的。
- (1)創(chuàng)建一個(gè)指針對(duì)象,指向當(dāng)前數(shù)據(jù)結(jié)構(gòu)的起始位置。也就是說(shuō),遍歷器對(duì)象本質(zhì)上,就是一個(gè)指針對(duì)象。
- (2)第一次調(diào)用指針對(duì)象的next方法,可以將指針指向數(shù)據(jù)結(jié)構(gòu)的第一個(gè)成員。
- (3)第二次調(diào)用指針對(duì)象的next方法,指針就指向數(shù)據(jù)結(jié)構(gòu)的第二個(gè)成員。
- (4)不斷調(diào)用指針對(duì)象的next方法,直到它指向數(shù)據(jù)結(jié)構(gòu)的結(jié)束位置。
使對(duì)象能夠使用 for…of
const obj = { // 使用計(jì)算屬性,用[]存表達(dá)式屬性名 // 1、Iterable,對(duì)象必須要有一個(gè)Symbol.iterator屬性 [Symbol.iterator]: function () { return { // 2、Iterator,返回的對(duì)象有一個(gè)next()方法 next: function () { // 3、IterationResult,next()方法返回一個(gè)對(duì)象 return { value: 'zce', done: true } } } } } for (const item of obj) { console.log('循環(huán)體', item) }
使對(duì)象能夠使用 for…of,完整的代碼
const obj = { store: ['foo', 'bar', 'baz'], [Symbol.iterator]: function () { let index = 0 const self = this return { next: function () { const result = { value: self.store[index], done: index >= self.store.length } index++ return result } } } } for (const item of obj) { console.log('循環(huán)體', item) }
迭代器模式(設(shè)計(jì)模式之一)
迭代器的另外一個(gè)主要用途:迭代器模式
ES2016 新增特性
數(shù)組的includes方法
// Array.prototype.includes ----------------------------------- const arr = ['foo', 1, NaN, false] // 找到返回元素下標(biāo) console.log(arr.indexOf('foo')) // 找不到返回 -1 console.log(arr.indexOf('bar')) // 無(wú)法找到數(shù)組中的 NaN console.log(arr.indexOf(NaN)) // 直接返回是否存在指定元素 console.log(arr.includes('foo')) // 能夠查找 NaN console.log(arr.includes(NaN))
指數(shù)運(yùn)算符
// 指數(shù)運(yùn)算符 --------------------------------------------------- console.log(Math.pow(2, 10)) console.log(2 ** 10)
ES2017 新增特性
Object新增方法
Object.values —— 類似Object.keys,返回對(duì)象的值數(shù)組
Object.entries —— 以數(shù)組的形式返回對(duì)象中的鍵值對(duì),結(jié)合for…of可以遍歷obj
const obj = { foo: 'value1', bar: 'value2' } // Object.values ----------------------------------------------------------- console.log(Object.values(obj)) // Object.entries ---------------------------------------------------------- console.log(Object.entries(obj)) // 比iterator 更簡(jiǎn)單,直接先將obj轉(zhuǎn)換成數(shù)組,再使用 for...of for (const [key, value] of Object.entries(obj)) { console.log(key, value) } console.log(new Map(Object.entries(obj)))
Object.getOwnPropertyDescriptors —— 獲取對(duì)象屬性的完整信息,主要配合ES5的get、set使用
Object.assign 獲取不到set、get信息
const p1 = { firstName: 'Lei', lastName: 'Wang', get fullName () { return this.firstName + ' ' + this.lastName } } // console.log(p1.fullName) // const p2 = Object.assign({}, p1) // p2.firstName = 'zce' // console.log(p2) const descriptors = Object.getOwnPropertyDescriptors(p1) // console.log(descriptors) const p2 = Object.defineProperties({}, descriptors) p2.firstName = 'zce' console.log(p2.fullName)
String新增方法
String.prototype.padStart / String.prototype.padEnd
const books = { html: 5, css: 16, javascript: 128 } // for (const [name, count] of Object.entries(books)) { // console.log(name, count) // } for (const [name, count] of Object.entries(books)) { console.log(`${name.padEnd(16, '-')}|${count.toString().padStart(3, '0')}`) }
在函數(shù)參數(shù)中添加尾逗號(hào)
const arr = [ 100, 200, 300, 400, ] const arr = [ 100, 200, 300 ]
新增Async/Await異步編程語(yǔ)法糖
來(lái)自于ES2017標(biāo)準(zhǔn);async、await能夠更方便的進(jìn)行異步編程,且通常需要成對(duì)使用;
1、async、await相對(duì)于generate函數(shù)升級(jí)提升的地方:
- (1)內(nèi)置執(zhí)行器
- (2)更好的語(yǔ)義
- (3)更好的擴(kuò)展器
- (4)返回值是promise
2、async、await的返回值
- (1)async的返回值是promise對(duì)象;但是需要注意:
1、async函數(shù)返回一個(gè) Promise 對(duì)象。
2、async函數(shù)內(nèi)部return語(yǔ)句返回的值,會(huì)成為then方法回調(diào)函數(shù)的參數(shù)。
async function f() { return 'hello world'; } f().then(v => console.log(v)) // "hello world"
- (2)await返回值根據(jù)后面的參數(shù)不同而不同,有兩種;
3、await 后面的參數(shù)
- (1)await后面跟一個(gè)promise對(duì)象;=> 返回promise對(duì)象的結(jié)果;
- (2)await后面跟一個(gè)值;=> 直接返回該值;
4、錯(cuò)誤處理方法
如果await后面的promise異步操作出錯(cuò),那么等同于async函數(shù)返回的 Promise 對(duì)象被reject。最好把a(bǔ)wait命令放在try…catch代碼塊中
async function f() { await new Promise(function (resolve, reject) { throw new Error('出錯(cuò)了'); }); } f() .then(v => console.log(v)) .catch(e => console.log(e)) async function myFunction() { try { await somethingThatReturnsAPromise(); } catch (err) { console.log(err); } } // 另一種寫法 async function myFunction() { await somethingThatReturnsAPromise() .catch(function (err) { console.log(err); }); }
5、并發(fā)/循環(huán)異步請(qǐng)求的處理
(1)如果是串行執(zhí)行異步請(qǐng)求,需要同步等待,會(huì)比較耗時(shí);
let foo = await getFoo(); let bar = await getBar(); // 1、循環(huán)里面的串行執(zhí)行: async function dbFuc(db) { let docs = [{}, {}, {}]; for (let doc of docs) { await db.post(doc); } } // 2、錯(cuò)誤的串行執(zhí)行:?why?思考?forEach里面的async應(yīng)該是異步同時(shí)執(zhí)行的,沒(méi)有await? function dbFuc(db) { //這里不需要 async let docs = [{}, {}, {}]; // 可能得到錯(cuò)誤結(jié)果 docs.forEach(async function (doc) { await db.post(doc); }); }
(2)并行執(zhí)行——等待所有響應(yīng),再執(zhí)行下一個(gè)步驟;
async function dbFuc(db) { let docs = [{}, {}, {}]; let promises = docs.map((doc) => db.post(doc)); let results = await Promise.all(promises); console.log(results); } // 或者使用下面的寫法 async function dbFuc(db) { let docs = [{}, {}, {}]; let promises = docs.map((doc) => db.post(doc)); let results = []; for (let promise of promises) { results.push(await promise); } console.log(results); }
(3)并行執(zhí)行——不等待所有響應(yīng),回來(lái)一個(gè)回調(diào)一個(gè);
// 可以不要在for里面await;也不要寫成串行的回調(diào); // 是在for里面寫異步方法的調(diào)用?例如: let docs = [{}, {}, {}]; for (let doc of docs) { db.post(doc).then((res)=>{}); }
6、async、await原理(利用generator實(shí)現(xiàn)async、await)
async、await底層封裝起來(lái)了看不見(jiàn)代碼實(shí)現(xiàn)
可以利用iterator或者generator函數(shù),進(jìn)行封裝實(shí)現(xiàn);參考代碼:(未完待續(xù))
ES2019 前定義的數(shù)據(jù)類型:8種
6+1 種原始數(shù)據(jù)類型 + bigInt(下個(gè)版本)
-
null
-
undefined
-
number
-
string
-
boolean
-
Symbol(ES2015)
-
BigInt(stage-4,下個(gè)版本出標(biāo)準(zhǔn)化)
【