前言
筆記僅記錄了相比于第一次學(xué)習(xí),重新理解的知識點
完整內(nèi)容詳見:《ECMAScript 6 入門》 阮一峰
總結(jié)
經(jīng)歷兩個星期結(jié)合ES6的React實踐,決定再回頭看一遍阮一峰的ES6教程,發(fā)現(xiàn)收獲多多,??闯P?。
第一遍看時,比較敷衍,沒有實踐自然也理解不深,綜合來說,阮一峰的教程更適合查漏補缺,而不是作為入門教材。
索引
- 解構(gòu)賦值的用途
- 尾調(diào)用優(yōu)化
- 擴展運算符的用途
- 數(shù)組的方法擴展
- 對象
- Set類型 : distinct Array
- Map類型:可擴展鍵名,值—值對
- Proxy對象
- Promise對象
- Iterator 迭代器
- Generator生成器
- async函數(shù)
- Class 類
1. 解構(gòu)賦值的用途
① 交換變量值: [x, y] = [y, x]
② 函數(shù)返回值的獲取更便利: let [a, b, c ] = func()
③ 函數(shù)無序傳參
有序傳參:function func([x,y,z]) { } func([1,2,3])
無序傳參:function func({x, y, z}) { } func({z: 3, y: 2 , x: 1})
④ 提取JSON數(shù)據(jù)更方便
⑤ 函數(shù)傳參可設(shè)置默認值,如預(yù)設(shè)Ajax請求的參數(shù)
當(dāng)傳入Ajax請求的參數(shù)不聲明async與cache值,默認都為true
jQuery.ajax = function (url, { async = true, cache = true}) {};
⑥ Map類型取鍵名/值 : for ( let [key, value] of map) { }
⑦ 加載CommonJS模塊中的指定方法: import { func1 , func2 } from '../common.js'
2. 尾調(diào)用優(yōu)化
在函數(shù)的最后一步(即return)中調(diào)用另一個函數(shù),形如return g(a,b);,叫做尾調(diào)用。
存儲于內(nèi)存中的函數(shù)調(diào)用記錄(包含了調(diào)用內(nèi)存位置、變量等信息),叫做調(diào)用幀,嵌套函數(shù)的調(diào)用幀形成了調(diào)用棧;這很浪費內(nèi)存。
因此在return句中采用尾調(diào)用,當(dāng)內(nèi)層函數(shù)的調(diào)用不再用到外層函數(shù)中的信息,就可用最新內(nèi)層函數(shù)的調(diào)用幀取代外層函數(shù)的調(diào)用幀,節(jié)省內(nèi)存。
3. 擴展運算符的用途
① 取代concat()合并數(shù)組: let arr = [...arr1, ...arr2];
② 與解構(gòu)賦值并用,截取部分數(shù)組: let [item, ...rest] = array;
③ 分解對象類型的函數(shù)返回值: var { data, code, msg } = getData();
④ 字符串轉(zhuǎn)數(shù)組: [...'hello] 等同于 'hello'.split('');
⑤ 正確識別32位的Unicode字符串: [ ...str ].length 獲取unicode字符串正確長度
4. 數(shù)組的方法擴展
① array.find(function) :查找第一個符合條件的數(shù)組元素
② array.findIndex() :與indexOf功能相同,但findIndex優(yōu)于可查找NaN元素
③ new Array(5).fill(0) :創(chuàng)建數(shù)組并且初始化為全0
④ 數(shù)組元素遍歷
array.keys() :遍歷鍵名
array.values() :遍歷鍵值
array.entries() :遍歷鍵值對
⑤ array.includes(value): 數(shù)組查找,可查找NaN
5. 對象
① let a = { [key]: value} :用表達式作鍵名
② Object.is(value1, value2 ): 嚴(yán)格一致,不會自動轉(zhuǎn)換類型,準(zhǔn)確性高于“===”
③ Object.assign(target, obj1, obj2 ): 合并對象屬性到第一個參數(shù)中;是淺拷貝(符合類型為引用)
④ object.__proto__屬性指向Object.prototype屬性
object.__proto__屬性推薦使用的三個操作方法:
Object.setPrototypeOf(object, prototype)
Object.getPrototypeOf(obj);
Object.create()
⑤ prototype與__proto__屬性
Array.prototype:Array原型的所有方法
new Array(3).__proto__ : 原型實例的自有屬性方法,內(nèi)包含了Array.prototype中的所有方法
⑥ 對象的擴展:let { x, y, ...z } = { x: 1, y: 2, a: 3 , b: 4} ; 則 z = { a: 3 , b: 4 }
6. Set類型 : distinct Array
① .add()
② .size
③ .delete()
④ .has(value)
⑤ .clear()
⑥ Set轉(zhuǎn)數(shù)組: Array.from(set)
數(shù)組去重: Array.from (new Set(array))
7. Map類型:可擴展鍵名,值—值對
① .size
② .set(key, value)
③ .get(key)
④ .has(key)
⑤ .delete(key)
⑥ .clear()
⑦ 遍歷的順序即插入的順序
⑧ Map轉(zhuǎn)數(shù)組: ...map
8. Proxy對象
進程與對象實體之間的攔截層
9. Reflect對象
用于部署對象的新方法;可以通過Reflect對象拿到語言內(nèi)部的方法,如Object.defineProperty
10. Promise對象
① 封裝了一個函數(shù)
② 對內(nèi)部函數(shù)返回的resolve與reject進行分發(fā)處理(.then與.catch)
③ Promise新建后,立即執(zhí)行
11. Iterator 迭代器
① Iterator.next()的返回值: {value: 'value', done: false} 或 { value: undefined, done: true}
② 悄悄調(diào)用了可遍歷數(shù)據(jù)的Iterator的情況:
解構(gòu)賦值有序?qū)ο螅〝?shù)組、set)、
擴展運算符...、
yield* 表達式: yield* [2,3,4] 等同于 yield 2; yield 3; yield 4;
③ let ... in :遍歷鍵名
④ let ... of:遍歷鍵值(適用于有Iterator接口的數(shù)據(jù))
12. Generator生成器
① 相當(dāng)于一個封裝了多個狀態(tài)的狀態(tài)機
② 作用:生成并且返回一個遍歷器對象
③ 調(diào)用后并不立即執(zhí)行,而是返回一個指向內(nèi)部狀態(tài)的指針對象(遍歷器對象)
④ 調(diào)用iterator.next(),才是真正執(zhí)行內(nèi)部函數(shù)的時機
⑤ yield可以嵌入普通語句中,但要放在圓括號中: console.log( 'hello' + (yield 123) );
⑥ yield表達式本身的返回值是undefined,但可以用next(value)對上一個yield表達式賦值
⑦ yield * generator():在一個生成器函數(shù)中調(diào)用另一個生成器函數(shù)
⑧ 封裝異步函數(shù),實現(xiàn)回調(diào)
function* demo () {
// do something Part1
yield go(); // 相當(dāng)于分離了異步的兩個階段,part1與part2
// do something Part2
}
let g = demo();
g.next(); // 執(zhí)行part1
g.next(); // part1執(zhí)行完之后,再執(zhí)行part2
⑨ 重點理解:
Generator 函數(shù)是分段執(zhí)行的,yield表達式是暫停執(zhí)行的標(biāo)記,而next方法可以恢復(fù)執(zhí)行。
在第一次調(diào)用.next()時,執(zhí)行到yield語句(yield語句本身也被執(zhí)行)。等下一次next調(diào)用,執(zhí)行下一段包含yield語句的代碼段。
function* demo () {
do thing 1
yield y1;
<---第一次執(zhí)行next,執(zhí)行到此處---->
do thing 2
yield y2;
<---第二次執(zhí)行next,執(zhí)行到此處---->
do thing 3
yield y3;
<---第三次執(zhí)行next,執(zhí)行到此處---->
do thing 4
yield y4;
<---第四次執(zhí)行next,執(zhí)行到此處---->
}
// 代碼實例
var a = 0;
function* demo() {
console.log('in demo a = 3')
console.log(yield a=3);
console.log('in demo a = 4')
console.log(yield a=4);
console.log('in demo a = 5')
console.log(yield a=5);
}
let g = demo();
console.log('首次next');
console.log(a);
console.log( g.next());
console.log(a);
console.log('二次next')
console.log(a);
console.log( g.next())
console.log(a);
console.log('三次next')
console.log(a);
console.log( g.next())
console.log(a);

13. async函數(shù)
是generator的語法糖,簡化了異步操作。相比generator,async具有以下優(yōu)點:
① 內(nèi)置執(zhí)行器,單行調(diào)用即可完成generator函數(shù)的所有.next()
② 更具有語義性
③ 適用性更廣
yield命令:只能后跟 Thunk 或Promise
await命令:可后跟Promise對象與原始值
④ async函數(shù)的返回值是Promise對象
async將generator返回的Iterator對象自動執(zhí)行后,并將結(jié)果封裝為一個Promise對象,便于后期處理。
return await 123; ==> 轉(zhuǎn)為resolve狀態(tài)的Promise對象
async中return語句返回值,傳入.then()作回調(diào)參數(shù)。
return Promise.reject('出錯了'); ==> 轉(zhuǎn)為reject狀態(tài)的Promise對象
async中拋出錯誤,返回reject狀態(tài)的Promise對象,傳入.catch()方法
⑤ forEach中的async是并發(fā)操作的,應(yīng)該改用for循環(huán)
// 不推薦用forEach寫法
function dbFuc(db) { //這里不需要 async
let docs = [{}, {}, {}];
// 可能得到錯誤結(jié)果
docs.forEach(async function (doc) {
await db.post(doc);
});
}
// 推薦用for循環(huán)
async function dbFuc(db) {
let docs = [{}, {}, {}];
for (let doc of docs) {
await db.post(doc);
}
}
14. Class 類
① super
super(): 代表父類的構(gòu)造函數(shù)傳入父類的this,等同于Class.prototype.constructor.call(this)
super:指向父類的原型對象,等同于Class.prototype,可用于調(diào)用父類的靜態(tài)方法
② prototype 與__proto__
子類的__proto__ 指向父類,表示構(gòu)造函數(shù)的繼承
子類的prototype.__proto__指向父類的prototype屬性, 表示方法的繼承
子類實例的__proto__.__proto__指向父類實例的__proto__屬性