做者:JowayYoung
倉庫:Github、CodePen
博客:官網、掘金、思否、知乎
公衆號:IQ前端
特別聲明:原創不易,未經受權不得轉載或抄襲,如需轉載可聯繫筆者受權前端
第三次閱讀阮一峯老師的《ES6標準入門》了,之前閱讀時不細心,不少地方都是一目十行。最近此次閱讀都是逐個逐個字來讀,發現不少之前都沒有注意到的知識點,爲了方便記憶和預覽所有ES6特性
,因此寫下本文。node
如下提到的《ES6標準入門》統一使用《ES6》這個名稱來代替,而最新的ES6版本也是截止到當前的ES2020
複製代碼
本文的知識點徹底是參考或摘錄《ES6》裏的語句,有部分語句爲了方便理解和記憶,進行了相贊成思的轉義,同時對知識點進行歸類劃分。爲了讓你們能集中精力來記住這些特性,全文一句廢話和題外話都沒有,所有模塊以筆記的形式進行書寫,若是看得不是很慣建議對照《ES6》的內容來學習。git
本文整理出來的筆記都是書中的精華內容,囊括了整個ES6體系
的全部特性,很是方便你們從新認識所有ES6特性
。半小時的閱讀就可對ES6
有一個全面的瞭解,可認爲是一本ES6特性小字典
,收藏後可隨時查閱。即便看不完也要拉到本文末尾喔,有個大彩蛋,嘻嘻!es6
ES6是ECMA
爲JavaScript
制定的第6個標準版本,相關歷史可查看此章節《ES6-ECMAScript6簡介》。github
標準委員會最終決定,標準在每一年6月正式發佈並做爲當年的正式版本,接下來的時間裏就在此版本的基礎上進行改動,直到下一年6月草案就天然變成新一年的版本,這樣一來就無需之前的版本號,只要用年份標記便可。ECMAscript 2015
是在2015年6月
發佈ES6的第一個版本。以此類推,ECMAscript 2016
是ES6的第二個版本、 ECMAscript 2017
是ES6的第三個版本。ES6既是一個歷史名詞也是一個泛指,含義是5.1版本
之後的JavaScript下一代標準
,目前涵蓋了ES2015
、ES2016
、ES2017
、ES2018
、ES2019
、ES2020
。web
因此有些文章上提到的ES7
(實質上是ES2016
)、ES8
(實質上是ES2017
)、ES9
(實質上是ES2018
)、ES10
(實質上是ES2019
)、ES11
(實質上是ES2020
),實質上都是一些不規範的概念。從ES1到ES6,每一個標準都是花了好幾年甚至十多年才制定下來,你一個ES6到ES7,ES7到ES8,才用了一年,按照這樣的定義下去,那不是很快就ES20了。用正確的概念來講ES6目前涵蓋了ES2015、ES2016、ES2017、ES2018、ES2019、ES2020。正則表達式
另外,ES6更新的內容主要分爲如下幾點編程
做用json
function() {}
{}
var命令
在全局代碼中執行const命令
和let命令
只能在代碼塊中執行const命令
聲明常量後必須立馬賦值let命令
聲明變量後可立馬賦值或使用時賦值var
、const
、let
、function
、class
、import
重點難點segmentfault
const命令
和let命令
不存在變量提高const命令
和let命令
聲明變量以前,該變量都不可用const [a, b, c, d, e] = "hello"
const { toString: s } = 123
const { toString: b } = true
const { x, y } = { x: 1, y: 2 }
const { x, y = 2 } = { x: 1 }
const { x, y: z } = { x: 1, y: 2 }
Iterator接口
可採用數組形式的解構賦值const [x, y] = [1, 2]
const [x, y = 2] = [1]
function Func([x = 0, y = 1]) {}
function Func({ x = 0, y = 1 } = {}) {}
應用場景
[x, y] = [y, x]
const [x, y, z] = Func()
Func([1, 2])
const { name, version } = packageJson
function Func({ x = 1, y = 2 } = {}) {}
for (let [k, v] of Map) {}
const { readFile, writeFile } = require("fs")
重點難點
undefined
undefined
undefined
和null
沒法轉爲對象,所以沒法進行解構大括號包含
表示Unicode字符(\u{0xXX}
或\u{0XXX}
)for-of
遍歷字符串String.fromCodePoint()
的逆操做)新字符串
(Unicode正規化)新字符串
重點難點
4個字節儲存
的Unicode字符
上0b或0B開頭
表示二進制(0bXX
或0BXX
)0o或0O開頭
表示二進制(0oXX
或0OXX
)-2^53
)2^53
)正數1
、負數-1
、零0
)e^n - 1
1 + n
的天然對數(Math.log(1 + n)
){ prop, method() {} }
)[]
定義鍵([prop]
,不能與上同時使用)get/set 函數名
(屬性的描述對象在get
和set
上)bound 函數名
anonymous
enumerable
method() {}
)屬性遍歷
自身
、可繼承
、可枚舉
、非枚舉
、Symbol
for-in
:遍歷對象自身可繼承可枚舉
屬性Object.keys()
:返回對象自身可枚舉
屬性鍵組成的數組Object.getOwnPropertyNames()
:返回對象自身非Symbol
屬性鍵組成的數組Object.getOwnPropertySymbols()
:返回對象自身Symbol
屬性鍵組成的數組Reflect.ownKeys()
:返回對象自身所有
屬性鍵組成的數組[...arr]
,至關於rest/spread參數
的逆運算)Iterator接口
的數據結構爲真正數組,返回新數組
包含length的對象
、Arguments對象
、NodeList對象
String
、Set結構
、Map結構
、Generator函數
undefined
(空位處理規不一,建議避免出現)擴展應用
const arr = [...arr1]
const arr = [...arr1, ...arr2]
arr.push(...arr1)
Math.max.apply(null, [x, y])
=> Math.max(...[x, y])
[..."hello"]
[...Arguments, ...NodeList]
[...String, ...Set, ...Map, ...Generator]
const [x, ...rest/spread] = [1, 2, 3]
Array.from("hello").length
=> [..."hello"].length
重點難點
keys()
、values()
、entries()
返回的遍歷器對象,可用for-of
自動遍歷或next()
手動遍歷function Func(x = 1, y = 2) {}
const
或let
再次聲明function Func({ x = 1, y = 2 } = {}) {}
function Func(x = throwMissing()) {}
undefined
,代表此參數可省略:Func(undefined, 1)
Arguments對象
rest/spread參數
空字符串
(ES5)、變量名
(ES6)函數名
(ES5和ES6)bound 函數名
(ES5和ES6)anonymous
(ES5和ES6)() => {}
x => {}
(x, y) => {}
({x, y}) => {}
this
的機制,而是根本沒有本身的this
,致使內部的this
就是外層代碼塊的this
this
,所以不能用做構造函數function f(x) { return g(x); }
箭頭函數誤區
this
是定義時所在的對象
而不是使用時所在的對象
this
指向固定化,這種特性頗有利於封裝回調函數構造函數
,所以箭頭函數不可以使用new命令
yield命令
,所以箭頭函數不能用做Generator函數
Arguments對象
,此對象在函數體內不存在(可用rest/spread參數
代替)正則對象
,尾參數爲正則修飾符
(返回的正則表達式會忽略原正則表達式的修飾符)match()
、replace()
、search()
、split()
內部調用轉爲調用RegExp
實例對應的RegExp.prototype[Symbol.方法]
\uFFFF
的Unicode字符
點字符
(.)Unicode表示法
量詞
預約義模式
i修飾符
轉義
g修飾符
做用相似)u修飾符
y修飾符
重點難點
y修飾符
隱含頭部匹配標誌^
y修飾符
對match()
只能返回第一個匹配,必須與g修飾符
聯用才能返回全部匹配const set = Symbol(str)
Symbol值
(不登記在全局環境)Symbol值
,如存在此參數則返回原有的Symbol值
(先搜索後建立,登記在全局環境)Symbol值
的描述(只能返回Symbol.for()
的key
)Symbol值
的數組instanceof運算符
判斷是否爲此對象的實例時會調用此方法Array.prototype.concat()
時是否可展開String.prototype.match()
調用時會從新定義match()
的行爲String.prototype.replace()
調用時會從新定義replace()
的行爲String.prototype.search()
調用時會從新定義search()
的行爲String.prototype.split()
調用時會從新定義split()
的行爲for-of
時會調用指定的默認遍歷器Object.prototype.toString()
調用時其返回值會出如今toString()
返回的字符串之中表示對象的類型with
時哪些屬性會被with環境
排除數據類型
Array
、Function
、Date
、RegExp
、Error
)應用場景
for-in
、for-of
、Object.keys()
、Object.getOwnPropertyNames()
、JSON.stringify()
返回,只能經過Object.getOwnPropertySymbols
返回window
和global
),使用Symbol.for()
來模擬全局的Singleton模式
重點難點
Symbol()
生成一個原始類型的值不是對象,所以Symbol()
前不能使用new命令
Symbol()
參數表示對當前Symbol值
的描述,相同參數的Symbol()
返回值不相等Symbol值
不能與其餘類型的值進行運算Symbol值
可經過String()
或toString()
顯式轉爲字符串Symbol值
做爲對象屬性名時,此屬性是公開屬性,但不是私有屬性Symbol值
做爲對象屬性名時,只能用方括號運算符([]
)讀取,不能用點運算符(.
)讀取Symbol值
做爲對象屬性名時,不會被常規方法遍歷獲得,可利用此特性爲對象定義非私有但又只用於內部的方法
const set = new Set(arr)
Iterator接口
的數據結構應用場景
[...new Set(str)].join("")
[...new Set(arr)]
或Array.from(new Set(arr))
const a = new Set(arr1)
、const b = new Set(arr2)
new Set([...a, ...b])
new Set([...a].filter(v => b.has(v)))
new Set([...a].filter(v => !b.has(v)))
let set = new Set(arr)
set = new Set([...set].map(v => v * 2))
或set = new Set(Array.from(set, v => v * 2))
重點難點
NaN
時,只會存在一個NaN
5 !== "5"
)keys()
和values()
的行爲徹底一致,entries()
返回的遍歷器同時包括鍵和值且兩值相等const set = new WeakSet(arr)
Iterator接口
的數據結構應用場景
WeakSet結構
中的引用就會自動消重點難點
弱引用
,垃圾回收機制不考慮WeakSet結構
對此成員的引用WeakSet結構不可遍歷
WeakSet結構
中const set = new Map(arr)
Iterator接口
且每一個成員都是一個雙元素數組的數據結構重點難點
NaN
做爲鍵時,只會存在一個以NaN
做爲鍵的值Object結構
提供字符串—值
的對應,Map結構
提供值—值
的對應const set = new WeakMap(arr)
Iterator接口
且每一個成員都是一個雙元素數組的數據結構應用場景
重點難點
弱引用
,垃圾回收機制不考慮WeakMap結構
對此成員鍵的引用WeakMap結構不可遍歷
WeakMap結構
中只是鍵而不是值
,值依然是正常引用const proxy = new Proxy(target, handler)
{ proxy, revoke }
,經過revoke()取消代理)k in obj
,返回布爾delete obj[k]
,返回布爾Object.defineProperty()
、Object.defineProperties()
,返回布爾for-in
、Object.keys()
、Object.getOwnPropertyNames()
、Object.getOwnPropertySymbols()
,返回數組Object.getOwnPropertyDescriptor()
,返回對象instanceof
、Object.getPrototypeOf()
、Object.prototype.__proto__
、Object.prototype.isPrototypeOf()
、Reflect.getPrototypeOf()
,返回對象Object.setPrototypeOf()
,返回布爾Object.isExtensible()
,返回布爾Object.preventExtensions()
,返回布爾proxy()
、proxy.apply()
、proxy.call()
new proxy()
應用場景
Proxy.revocable()
:不容許直接訪問對象,必須經過代理訪問,一旦訪問結束就收回代理權不容許再次訪問get()
:讀取未知屬性報錯、讀取數組負數索引的值、封裝鏈式操做、生成DOM嵌套節點set()
:數據綁定(Vue數據綁定實現原理)、確保屬性值設置符合要求、防止內部屬性被外部讀寫has()
:隱藏內部屬性不被發現、排除不符合屬性條件的對象deleteProperty()
:保護內部屬性不被刪除defineProperty()
:阻止屬性被外部定義ownKeys()
:保護內部屬性不被遍歷重點難點
Proxy
起做用,必須針對實例
進行操做,而不是針對目標對象
進行操做直接通向原對象
不可讀寫/擴展/配置/枚舉
時,使用攔截方法會報錯this
指向Proxy代理
Object方法
的默認行爲Object.getOwnPropertyNames()
+Object.getOwnPropertySymbols()
)設計目的
Object
屬於語言內部的方法
放到Reflect
上false
Object操做
變成函數行爲
Proxy
與Reflect
相輔相成廢棄方法
Object.defineProperty()
=> Reflect.defineProperty()
Object.getOwnPropertyDescriptor()
=> Reflect.getOwnPropertyDescriptor()
重點難點
Proxy方法
和Reflect方法
一一對應Proxy
和Reflect
聯合使用,前者負責攔截賦值操做
,後者負責完成賦值操做
數據綁定:觀察者模式
const observerQueue = new Set();
const observe = fn => observerQueue.add(fn);
const observable = obj => new Proxy(obj, {
set(tgt, key, val, receiver) {
const result = Reflect.set(tgt, key, val, receiver);
observerQueue.forEach(v => v());
return result;
}
});
const person = observable({ age: 25, name: "Yajun" });
const print = () => console.log(`${person.name} is ${person.age} years old`);
observe(print);
person.name = "Joway";
複製代碼
prototype
上,可看做構造函數的另外一種寫法(Class === Class.prototype.constructor
)new命令
生成實例時自動調用this
構造函數的繼承
(老是指向父類
)__proto__
)屬性方法的繼承
(老是指向父類的prototype
)不會被實例繼承
,只能經過類來調用static
定義方法,該方法不會被實例繼承
,只能經過類來調用(方法中的this
指向類,而不是實例)this
,再將父類的屬性方法添加到this
上(Parent.apply(this)
)this
上(調用super()
),再用子類構造函數修改this
super()
,內部this
指向繼承的當前子類
(super()
調用後纔可在構造函數中使用this
)普通方法
中指向父類的原型對象
,在靜態方法
中指向父類
constructor() { super(); }
定義繼承父類,沒有書寫則顯示定義
super()
,不然得不到父類的this
super
上調用父類靜態屬性方法實例的原型
,全部在類中定義的屬性方法都會被實例繼承
this
指定到自身上(使用Class.hasOwnProperty()
可檢測到)Class.__proto__.hasOwnProperty()
可檢測到)const Class = class {}
class
後的類名[prop]
* mothod() {}
async mothod() {}
this.mothod = this.mothod.bind(this)
this.mothod = () => this.mothod()
this
指向類最頂層
原生構造函數
重點難點
Object.assign()
可方便地一次向類添加多個方法(Object.assign(Class.prototype, { ... })
)non-enumerable
)this
),可指定返回另外一個對象Descriptor對象
上new.target === Class
寫出不能獨立使用必須繼承後才能使用的類this
指向子類實例,經過super
對某個屬性賦值,賦值的屬性會變成子類實例的屬性super
時,必須顯式指定是做爲函數仍是做爲對象使用extends
不只可繼承類還可繼承原生的構造函數私有屬性方法
const name = Symbol("name");
const print = Symbol("print");
class Person {
constructor(age) {
this[name] = "Bruce";
this.age = age;
}
[print]() {
console.log(`${this[name]} is ${this.age} years old`);
}
}
複製代碼
繼承混合類
function CopyProperties(target, source) {
for (const key of Reflect.ownKeys(source)) {
if (key !== "constructor" && key !== "prototype" && key !== "name") {
const desc = Object.getOwnPropertyDescriptor(source, key);
Object.defineProperty(target, key, desc);
}
}
}
function MixClass(...mixins) {
class Mix {
constructor() {
for (const mixin of mixins) {
CopyProperties(this, new mixin());
}
}
}
for (const mixin of mixins) {
CopyProperties(Mix, mixin);
CopyProperties(Mix.prototype, mixin.prototype);
}
return Mix;
}
class Student extends MixClass(Person, Kid) {}
複製代碼
export default Person
(導入時可指定模塊任意名稱,無需知曉內部真實名稱)export const name = "Bruce"
export { age, name, sex }
(推薦)export { name as newName }
import Person from "person"
import * as Person from "person"
import { age, name, sex } from "person"
import { name as newName } from "person"
import "person"
import Person, { name } from "person"
export命令
和import命令
結合在一塊兒寫成一行,變量實質沒有被導入當前模塊,至關於對外轉發接口,致使當前模塊沒法直接使用其導入變量
export { default } from "person"
export * from "person"
export { age, name, sex } from "person"
export { name as newName } from "person"
export { name as default } from "person"
export { default as name } from "person"
默認導出
和更名導出
結合使用可以使模塊具有繼承性use strict
)模塊方案
加載方式
加載實現
<script>
進行同步或異步加載腳本
<script src=""></script>
<script src="" defer></script>
(順序加載,渲染完再執行)<script src="" async></script>
(亂序加載,下載完就執行)<script type="module" src=""></script>
(默認是Defer異步加載)CommonJS和ESM的區別
CommonJS
輸出值的拷貝
,ESM
輸出值的引用
CommonJS
一旦輸出一個值,模塊內部的變化就影響不到這個值ESM
是動態引用且不會緩存值,模塊裏的變量綁定其所在的模塊,等到腳本真正執行時,再根據這個只讀引用到被加載的那個模塊裏去取值CommonJS
是運行時加載,ESM
是編譯時加載
CommonJS
加載模塊是對象(即module.exports
),該對象只有在腳本運行完纔會生成ESM
加載模塊不是對象,它的對外接口只是一種靜態定義,在代碼靜態解析階段就會生成Node加載
CommonJS
和ESM
互不兼容,目前解決方案是將二者分開,採用各自的加載方案ESM
採用.mjs
後綴文件名
require()
不能加載.mjs文件
,只有import命令
纔可加載.mjs文件
.mjs文件
裏不能使用require()
,必須使用import命令
加載文件node --experimental-modules file.mjs
import命令
目前只支持加載本地模塊(file:協議
),不支持加載遠程模塊.mjs
、.js
、.json
、node
)package.json
的main字段
指定的腳本index
四個後綴名文件(.mjs
、.js
、.json
、node
)arguments
、exports
、module
、require
、this
、__dirname
、__filename
require()
,只能使用import()
module.exports
轉化成export default
CommonJS
輸出緩存機制在ESM
加載方式下依然有效import命令
加載CommonJS模塊
時,不容許採用按需導入
,應使用默認導入
或總體導入
循環加載
腳本A
的執行依賴腳本B
,而腳本A
的執行又依賴腳本B
require()
首次加載腳本就會執行整個腳本,在內存裏生成一個對象緩存下來,二次加載腳本時直接從緩存中獲取import命令
加載變量不會被緩存,而是成爲一個指向被加載模塊的引用重點難點
this
指向undefined
,不該該在頂層代碼使用this
export命令
輸出的接口與其對應的值是動態綁定關係
,即經過該接口可獲取模塊內部實時的值import命令
大括號裏的變量名必須與被導入模塊對外接口的名稱相同import命令
輸入的變量只讀(本質是輸入接口),不容許在加載模塊的腳本里改寫接口import命令
命令具備提高效果,會提高到整個模塊的頭部,首先執行import語句
,只會執行一次export default
命令只能使用一次export default命令
導出的總體模塊,在執行import命令
時其後不能跟大括號
export default命令
本質是輸出一個名爲default
的變量,後面不能跟變量聲明語句
export default命令
本質是將後面的值賦給名爲default
的變量,可直接將值寫在其後export default命令
和export {}命令
可同時存在,對應複合導入
export命令
和import命令
可出如今模塊任何位置,只要處於模塊頂層便可,不能處於塊級做用域import()
加載模塊成功後,此模塊會做爲一個對象,看成then()
的參數,可以使用對象解構賦值
來獲取輸出接口Promise.all()
和import()
相結合來實現import()
和結合async/await
來書寫同步操做的代碼單例模式:跨模塊常量
// 常量跨文件共享
// person.js
const NAME = "Bruce";
const AGE = 25;
const SEX = "male";
export { AGE, NAME, SEX };
複製代碼
// file1.js
import { AGE } from "person";
console.log(AGE);
複製代碼
// file2.js
import { AGE, NAME, SEX } from "person";
console.log(AGE, NAME, SEX);
複製代碼
默認導入互換總體導入
import Person from "person";
console.log(Person.AGE);
複製代碼
import * as Person from "person";
console.log(Person.default.AGE);
複製代碼
next()
指向下一個成員,直接到結束位置(數據結構只要部署Iterator接口
就可完成遍歷操做)for-of
,Iterator接口
主要供for-of
消費for-of
(自動去尋找Iterator接口)Array
、Object
、Set
、Map
String
、Array
、Set
、Map
、TypedArray
、Arguments
、NodeList
Symbol.iterator
(具有此屬性被認爲可遍歷的iterable
){ done, value }
(必須部署)for-of
提早退出調用,返回{ done: true }
Generator函數
使用ForOf循環
Iterator接口
產生遍歷器對象(for-of
內部調用數據結構的Symbol.iterator()
)for-in
獲取索引
,for-of
獲取值
(可識別32位UTF-16字符)for-in
獲取索引
,for-of
獲取值
for-in
獲取鍵
,for-of
需自行部署for-of
獲取值
=> for (const v of set)
for-of
獲取鍵值對
=> for (const [k, v] of map)
包含length的對象
、Arguments對象
、NodeList對象
(無Iterator接口的類數組
可用Array.from()
轉換)Array
、Set
、Map
for-in
區別
for-in
同樣的簡潔語法,但沒有for-in
那些缺點、forEach()
,它可與break
、continue
和return
配合使用應用場景
Iterator接口
的數據結構的Symbol.iterator
Iterator接口
的數據結構轉爲數組yield*
後跟一個可遍歷的數據結構,會調用其遍歷器接口for-of
、Array.from()
、new Set()
、new WeakSet()
、new Map()
、new WeakMap()
、Promise.all()
、Promise.race()
pending
resolved
rejected
new Promise((resolve, reject) => {})
未完成
變爲成功
,在異步操做成功時調用,並將異步操做的結果做爲參數傳遞出去未完成
變爲失敗
,在異步操做失敗時調用,並將異步操做的錯誤做爲參數傳遞出去resolved狀態
和rejected狀態
的回調函數
resolved
時調用rejected
時調用(可選)Iterator接口
的數據結構fulfilled
,最終狀態纔會變成fulfilled
rejected
,最終狀態就會變成rejected
Iterator接口
的數據結構new Promise(resolve => resolve())
)
then()
的對象,執行then()
至關於執行此對象的then()
)resolved
resolved
rejected
的Promise對象(等價於new Promise((resolve, reject) => reject())
)應用場景
重點難點
pending
變爲resolved
、從pending
變爲rejected
Promise對象
就會當即執行,沒法中途取消pending
時,沒法得知目前進展到哪個階段resolved
或rejected
時,會觸發then()
綁定的回調函數resolve()
和reject()
的執行老是晚於本輪循環的同步任務then()
返回新實例,其後可再調用另外一個then()
then()
運行中拋出錯誤會被catch()
捕獲reject()
的做用等同於拋出錯誤resolved
時,再拋出錯誤是無效的,不會被捕獲,等於沒有拋出冒泡
性質,會一直向後傳遞直到被捕獲爲止,錯誤老是會被下一個catch()
捕獲then()
裏定義rejected
狀態的回調函數(不使用其第二參數)catch()
捕獲錯誤,不要使用then()
第二個參數捕獲catch()
捕獲錯誤,實例拋錯不會傳遞到外層代碼,即不會有任何反應
catch()
,一旦被rejected
並不會觸發Promise.all()
的catch()
Promise.reject()
的參數會原封不動地做爲rejected
的理由,變成後續方法的參數Generator函數
(該函數不執行)返回指向內部狀態的指針對象(不是運行結果)function* Func() {}
{ done, value }
(入參會被看成上一個yield命令表達式
的返回值)Generator函數
,返回{ done: true, value: 入參 }
Generator函數
體外拋出錯誤,在Generator函數
體內捕獲錯誤,返回自定義的new Errow()
return
聲明結束返回的值)
yield命令
就暫停執行後面的操做,並將其後表達式的值做爲返回對象的value
next()
時,再繼續往下執行直到遇到下一個yield命令
yield命令
就一直運行到Generator函數
結束,直到遇到return語句
爲止並將其後表達式的值做爲返回對象的value
Generator函數
沒有return語句
則返回對象的value
爲undefined
Generator函數
裏執行另外一個Generator函數
(後隨具備Iterator接口
的數據結構)for-of
自動調用next()
const obj = { method: function*() {} }
const obj = { * method() {} }
上下文環境
一旦遇到yield命令
就會暫時退出堆棧(但並不消失),全部變量和對象會凍結在當前狀態
,等到對它執行next()
時,這個上下文環境
又會從新加入調用棧,凍結的變量和對象恢復執行方法異同
next()
、throw()
、return()
本質上是同一件事,做用都是讓函數恢復執行且使用不一樣的語句替換yield命令
yield命令
替換成一個值
yield命令
替換成一個return語句
yield命令
替換成一個throw語句
應用場景
Generator函數
賦值給對象的Symbol.iterator
,從而使該對象具備Iterator接口
重點難點
next()
,指針就從函數頭部
或上次停下的位置
開始執行,直到遇到下一個yield命令
或return語句
爲止yield命令
,但會變成單純的暫緩執行函數
(仍是須要next()
觸發)yield命令
是暫停執行的標記,next()
是恢復執行的操做yield命令
用在另外一個表達式中必須放在圓括號
裏yield命令
用做函數參數或放在賦值表達式的右邊,可不加圓括號
yield命令
自己沒有返回值,可認爲是返回undefined
yield命令表達式
爲惰性求值,等next()
執行到此才求值Symbol.iterator
是此對象自己next()
從外部向內部注入不一樣的值,從而調整函數行爲next()
用來啓動遍歷器對象,後續纔可傳遞參數next()
時就能輸入值,可在函數外面再包一層next()
返回對象的done
爲true
,for-of
遍歷會停止且不包含該返回對象try-finally
且正在執行try
,那麼return()
會致使馬上進入finally
,執行完finally
之後整個函數纔會結束try-catch
,throw()
拋錯將被外部try-catch
捕獲throw()
拋錯要被內部捕獲,前提是必須至少執行過一次next()
throw()
被捕獲之後,會附帶執行下一條yield命令
throw()
拋錯只可能拋出在函數外部首次next()可傳值
function Wrapper(func) {
return function(...args) {
const generator = func(...args);
generator.next();
return generator;
}
}
const print = Wrapper(function*() {
console.log(`First Input: ${yield}`);
return "done";
});
print().next("hello");
複製代碼
Math.pow()
)SharedArrayBuffer
和Atomics
實現,將數據存儲在一塊共享內存空間中,這些數據可在JS主線程
和web-worker線程
之間共享Generator函數
和自動執行器spawn
包裝在一個函數裏Generator函數
的*
替換成async
,將yield
替換成await
async function Func() {}
const func = async function() {}
const func = async() => {}
const obj = { async func() {} }
class Cla { async Func() {} }
Thenable對象
:將其等同於Promise對象返回其結果await命令Promise對象
放到try-catch
中(可放多個)Async對Generator改進
應用場景
重點難點
Async函數
返回Promise對象
,可以使用then()
添加回調函數return返回值
會成爲後續then()
的出參rejected狀態
,被catch()
接收到await命令Promise對象
執行完纔會發生狀態改變,除非遇到return語句
或拋出錯誤
await命令Promise對象
變爲rejected狀態
,整個Async函數
都會中斷執行await命令Promise對象
放到try-catch
中await命令Promise對象
跟一個catch()
await命令Promise對象
可能變爲rejected狀態
,最好把其放到try-catch
中await命令Promise對象
若不存在繼發關係,最好讓它們同時觸發await命令
只能用在Async函數
之中,不然會報錯forEach()
執行async/await
會失效,可以使用for-of
和Promise.all()
代替Async函數
的執行而存在,執行完成就消失undefined
,而且從raw
上可獲取原字符串{ ...obj }
,至關於rest/spread參數
的逆運算)擴展應用
const obj = { __proto__: Object.getPrototypeOf(obj1), ...obj1 }
const obj = { ...obj1, ...obj2 }
{ ..."hello" }
{ ...[1, 2] }
const { x, ...rest/spread } = { x: 1, y: 2, z: 3 }
(不能複製繼承自原型對象的屬性)const obj = { x: 1, ...{ x: 2 } }
.
匹配任意單個字符(dotAll模式
)s修飾符
x
只有在y
後才匹配x
只有不在y
後才匹配Unicode某種屬性
的全部字符
\p{PropRule}
\P{PropRule}
\p{...}
和\P{...}
只對Unicode字符
有效,使用時需加上u修飾符
?<GroupName>
)
str.exec().groups.GroupName
const time = "2017-09-11"
、const regexp = /(?<year>\d{4})-(?<month>\d{2})-(?<day>\d{2})/u
time.replace(regexp, "$<day>/$<month>/$<year>")
Promise對象
變爲resolved狀態
才進入下一步行分隔符
和段分隔符
Object.entries()
的逆操做)穩定
catch()
中的參數可省略Symbol值
的描述this
window
global
self
globalThis
n
結尾)
Number.parseInt()
,將一個字符串轉換成指定進制的BigInt類型重點難點
bigint
undefined
且再也不往下執行)
obj?.prop
、obj?.[expr]
func?.(...args)
undefined
或null
,是則使用默認值Promise
)
import命令
被JS引擎靜態分析,先於模塊內的其餘語句執行,沒法取代require()
的動態加載功能,提案建議引入import()
來代替require()
require()
是同步加載,import()
是異步加載Iterator接口
的數據結構status
和value
,status
爲fulfilled
,value
爲返回值status
和reason
,status
爲rejected
,value
爲錯誤緣由do{}
)throw new Error()
,無需()
或{}
包括_
做爲千分位分隔符(增長數值的可讀性)?
表示單個參數佔位符,...
表示多個參數佔位符)f(x)
=> x |> f
)bind
、apply
、call
調用)
bar.bind(foo)
=> foo::bar
bar.apply(foo, arguments)
=> foo::bar(...arguments)
沙箱功能
,容許隔離代碼,防止被隔離的代碼拿到全局對象new Realm().global
static
定義屬性,該屬性不會被實例繼承
,只能經過類來調用#
定義屬性,該屬性只能在類內部訪問#
定義方法,該方法只能在類內部訪問@
註釋或修改類和類方法Iterator接口
的數據結構fulfilled
,最終狀態就會變成fulfilled
rejected
,最終狀態纔會變成rejected
then()
指定下一步流程,使用catch()
捕獲錯誤await命令
(借用await
解決模塊異步加載的問題)最後送你們一張完整的ES6特性圖,記得給我點個贊喔,算是對個人一種鼓勵。由於圖片實在太大沒法上傳,請關注IQ前端
或掃描文章底部二維碼
,後臺回覆ES6
,獲取高清的ES6所有特性記憶圖,助你輕鬆記住ES6所有特性。
❤️關注+點贊+收藏+評論+轉發❤️,原創不易,鼓勵筆者創做更多高質量文章
關注公衆號IQ前端
,一個專一於CSS/JS開發技巧的前端公衆號,更多前端小乾貨等着你喔
資料
免費領取學習資料進羣
拉你進技術交流羣IQ前端
,更多CSS/JS開發技巧只在公衆號推送