概覽
ES6,全稱ECMAScript 6.0,是JavaScript的下一版本標準,2015.06發布。
ES6主要是為了解決ES5的先天不足,比如JavaScript里沒有類的概念、內置集合對象Map和Set、迭代器、異步編程等。
特性
1 聲明與表達式
1.1 let 與 const
let 和 const 是在ES6中新增的兩個關鍵字。
let聲明的變量只在let命令所在的代碼塊內有效,不能重復聲明, 不存在變量提升。
var 定義的變量是在全局范圍內有效,可以重復聲明,存在變量提升。
{
console.log(a) // ReferenceError: Cannot access 'a' before initialization
let a = 0
console.log(a) // 0
let a = 1 // SyntaxError: Identifier 'a' has already been declared
}
console.log(a) // ReferenceError: a is not defined
const聲明一個只讀的常量,一旦聲明,常量的值就不能改變。意味著一旦聲明就必須初始化,否則會報錯。
const PI = "3.1415926";
console.log(PI) // 3.1415926
const MY_AGE; // SyntaxError: Missing initializer in const declaration
const 保證的不是變量的值不變,而是保證變量所指向的內存地址所保存的數據不允許改動。
1.2 解構賦值
解構賦值是對賦值運算符的擴展,是一種針對數組或者對象進行模式匹配,然后對其中的變量進行賦值。在代碼書寫上簡潔且易讀,語義更加清晰明了;也方便了復雜對象中數據字段的獲取。
數組模型解構(Array)
- 基本
let [a,b,c] = [1,2,3]
console.log(a) // 1
console.log(b) // 2
console.log(c) // 3
- 可嵌套
let [a,[[b],c]] = [1,[[2],3]]
- 可忽略
let [a, ,b] = [1,2,3]
- 不完全解構
let [a = 1, b] = []
console.log(a) // a = 1
console.log(b) // b = undefined
- 剩余運算符
let [a, ...b] = [1,2,3]
console.log(a) // a = 1
console.log(b) // b = [2,3]
- 字符串等
let [a,b,c,d,e] = 'hello'
console.log(a) // a = 'h'
console.log(b) // a = 'e'
console.log(c) // a = 'l'
console.log(d) // a = 'l'
console.log(e) // a = 'o'
- 解構默認值
let [a = 2] = [undefined]
console.log(a) // a = 2
當解構模式有匹配結果,且匹配結果是undefined時,會觸發默認值作為返回值
let [a = 3, b = a] = []; // a = 3, b = 3 let [a = 3, b = a] = [1]; // a = 1, b = 1 let [a = 3, b = a] = [1, 2]; // a = 1, b = 2
對象模型解構(Object)
- 基本
let { foo, bar } = { foo: 'aaa', bar: 'bbb' }
console.log(foo) // foo = 'aaa'
console.log(bar) // bar = 'bbb'
其它可參考數組模型的解構
1.3 Symbol
ES6引入了一種新的原始數據類型Symbol,表示獨一無二的值,最大的用法是用來定義對象的唯一屬性名。
- 基本用法
let sy = Symbol('kk')
console.log(sy) // Symbol(kk)
typeof(sy) // 'symbol'
//相同參數 Symbol() 返回的值不相等
let sy1 = Symbol('kk')
sy === sy1 // false
- 注意事項
- Symbol 作為對象屬性名時不能用.運算符,要用方括號。因為.運算符后面是字符串,所以取到的是字符串 sy 屬性,而不是 Symbol 值 sy 屬性。
- Symbol 值作為屬性名時,該屬性是公有屬性不是私有屬性,可以在類的外部訪問
- 不會出現在 for...in 、 for...of 的循環中,也不會被 Object.keys() 、 Object.getOwnPropertyNames() 返回
- 要讀取到一個對象的 Symbol 屬性,可以通過 Object.getOwnPropertySymbols() 和 Reflect.ownKeys() 取到
- Symbol.for()
類似單例模式,首先會在全局搜索被登記的 Symbol 中是否有該字符串參數作為名稱的 Symbol 值,如果有即返回該 Symbol 值,若沒有則新建并返回一個以該字符串參數為名稱的 Symbol 值,并登記在全局環境中供搜索。
let yellow = Symbol("Yellow");
let yellow1 = Symbol.for("Yellow");
yellow === yellow1; // false
let yellow2 = Symbol.for("Yellow");
yellow1 === yellow2; // true
- Symbol.keyFor()
Symbol.keyFor() 返回一個已登記的 Symbol 類型值的 key ,用來檢測該字符串參數作為名稱的 Symbol 值是否已被登記。
let yellow1 = Symbol.for("Yellow");
Symbol.keyFor(yellow1); // "Yellow"
2 內置對象
2.1 Map 與 Set
Map
Map 對象保存鍵值對。任何值(對象或者原始值)都可以作為一個鍵或者一個值。
Maps 和 Objects 的區別:
- 一個Object的鍵只能是字符串或者是Symbol, 但一個Map的鍵可以是任意值。
- Map中的鍵值是有序的(FIFO原則),而添加到對象中的鍵值則不是。
- Map中的鍵值對個數可以從size屬性獲取,而Object的鍵值對個數只能手動計算。
- Object都有自己的原型,原型鏈上的鍵名有可能和你自己在對象上設置的鍵名產生沖突。
-
基本使用
let myMap = new Map() myMap.set('key','value') // key is string myMap.get('key') // value myMap.set(NaN, 'not a number') // key is NaN
-
Map的迭代
for ... of
let myMap = new Map() myMap.set(0, 'zero') myMap.set(1, 'one') for(let [key,value] of myMap){ console.log(key + ' = ' + value) }
forEach()
myMap.forEach(function(key,value){ console.log(key + ' = ' + value) })
-
Map對象的操作
Map 與 Array 的轉換
let vkArr = [['key1','value1'],['key2','value2']] let myMap = new Map(vkArr) // 將一個二維數組轉換成 Map 對象 let outArr = Array.from(myMap) // 將一個Map 轉換成 Array
Map 的克隆
let originalMap = new Map([['key1','value1'],['key2','value2']]) let cloneMap = new Map(originalMap) console.log(originalMap === cloneMap) // false, Map對象構造函數生成實例,迭代出新的對象
Map 的合并
let first = new Map([[1, 'one'], [2, 'two'], [3, 'three'],]) let second = new Map([[1, 'uno'], [2, 'dos']]) let merged = new Map(...first, ...second) //合并Map對象時,如果鍵值重復,則后面的覆蓋前面的
Set
Set對象允許你存儲任何類型的唯一值,無論是原始值或者是對象引用。
Set對象存儲的值總是唯一的,所以需要判斷兩個值是否恒等。有幾個特殊值需要注意:
- +0 與 -0 在存儲判斷唯一性的時候是恒等的,所以不重復;
- undefined 與 undefined 是恒等的,所以不重復;
- NaN 與 NaN 是不恒等的,但是在Set中只能存一個,不重復;
-
基本使用
let mySet = new Set() mySet.add(1) mySet.add(5) mySet.add('string')
-
類型轉換
let mySet = new Set(['value1','value2','value3']) // Array 轉 Set let myArray = [...mySet] // 用 ...操作符 將Set 轉 Array //string 轉 set let mySet = new Set('hello') // Set(4) {'h','e','l','l','o'}
-
Set 對象作用
//數組去重 let mySet = new Set([1,2,3,4,4]) [...mySet] //[1,2,3,4] //并集 let a = new Set([1,2,3]) let b = new Set([4,3,2]) let union = new Set([...a, ...b]) // Set(4) {1,2,3,4} //交集 let intersect = new Set([...a].filter(x => b.has(x))) // Set(2) {2,3} //差集 let difference = new Set([...a].filter(x => !b.has(x))) // {1}
2.2 Proxy 與 Reflect
Proxy(代理)
Proxy 可以對目標對象的讀取、函數調用等操作進行攔截,然后進行操作處理。它不直接操作對象,而是像代理模式,通過對象的代理對象進行操作,在進行這些操作時,可以添加一些額外的操作。‘
-
基本用法
let target = { name: 'Tom', age: 24 } let handler = { get: function(target, key) { console.log('getting ' + key); return target[key]; // 不是target.key }, set: function(target, key, value) { console.log('setting ' + key); target[key] = value; } } let proxy = new Proxy(target, handler) proxy.name // 實際執行 handler.get proxy.age = 25 // 實際執行 handler.set
Reflect(映射)
Reflect 可以用于獲取目標對象的行為,與Object類似,但是更易讀,為操作對象提供了一個種更優雅的方式。它的方法與Proxy是對應的。
let exam = {
name: "Tom",
age: 24,
get info(){
return this.name + this.age;
}
}
Reflect.get(exam, 'name'); // "Tom"
Reflect.set(exam, 'age', 25); // true
組合使用
Reflect 對象的方法與Proxy對象的方法是一一對應的,所以Proxy對象的方法可以通過調用Reflect對象的方法獲取默認行為,然后進行額外操作。
let target = {
name: 'Tom',
age: 24
}
let handler = {
get: function (target, key) {
console.log('getting ' + key);
// return target[key];
return Reflect.get(target,key);
},
set: function (target, key, value) {
console.log('setting ' + key + ' value: ' + value);
// target[key] = value;
Reflect.set(target,key,value);
}
}
let proxy = new Proxy(target,handler)
proxy.age = 33
console.log('name is '+ proxy.name)
2.3 字符串
擴展的方法
方法名 | 方法描述 | 示例 |
---|---|---|
includes() | 返回boolean,判斷是否找到參數字符串 | 'hello'.includes('llo') // true |
startsWith() | 返回boolean,判斷參數字符串是否在原字符串的頭部 | 'hello'.startsWith('he') // true |
endsWith() | 返回boolean,判斷參數字符串是否在原字符串的尾部 | 'hello'.endsWith('o') //true |
indexOf() | 返回字串的位置 | 'hello'.indexOf('h') // 0 |
lastIndexOf() | 返回字串最后出現的位置 | 'hello'.lastIndexOf('h') // 4 |
repeat() | 返回新字符串,表示將字符串重復指定次數 | 'hello,'.repeat(2) // 'hello,hello,' |
padStart() | 返回新字符串,用參數字符從頭部(左側)補全字符串 | 'h'.padStart(5,'o') // 'ooooh' |
padEnd() | 返回新字符串,用參數字符從尾部(右側)補全字符串 | 'h'.padEnd(5,'o') // 'hoooo' |
模板字符串
模板字符串相當于加強版的字符串,用反引號`,除了作為普通字符串,還可以用來定義多行字符串,還可以在字符串中加入變量和表達式。
let name = 'Mike'
let age = 24
let info = `My name is ${name}, I am ${age + 1} years old next year.`
2.4 數值
N/A
2.5 對象
對象字面量
-
屬性的簡潔表示法。允許對象的屬性直接寫變量,這時候屬性名就是變量名,屬性值就是變量值。
const age = 12 const name = 'Amy' const person = {age, name} console.log(person) // {age: 12, name: 'Amy'}
-
方法名也可以簡寫
const person = { sayHi(){ console.log('Hi')} } //等同于 const person = { sayHi: function(){ console.log('Hi')} }
-
屬性名表達式
const obj = { ['hel' + 'lo']() { return 'Hi'} } obj.hello()
注意:屬性的簡潔表示法和屬性名表達式不能同時使用,否則會報錯
對象的拓展運算符
拓展運算符 (...) 用于取出參數對象所有可遍歷屬性然后拷貝到當前對象
-
基本用法
let person = {name: 'Amy', age: 12} let someone = {...person} console.log(someone) // {name: 'Amy', age: 12}
-
用于合并兩個對象
let age = {age: 12} let name = {name: 'Amy'} let person = {...age, ...name}
自定義的屬性和拓展運算符對象里面屬性相同的時候,自定義的屬性在拓展運算符后面,則拓展運算符對象內部同名的屬性將被覆蓋掉。
對象的新方法
-
Object.assign(target, source, ...)
用于將源對象的所有可枚舉屬性復制到目標對象中。
let target = {a: 1} let obj1 = {b: 2} let obj2 = {c: 3} Object.assign(target,obj1, obj2) console.log(target) // {a:1, b:2, c:3}
a. 如果目標對象和源對象有同名屬性,或者多個源對象有同名屬性,則后面的屬性會覆蓋前面的屬性。
b. 如果該函數只有一個參數,當參數為對象時,直接返回該對象;當參數不是對象時,會先將參數轉為對象后返回。
c. assign 的屬性拷貝是淺拷貝
-
Object.is(value1, value2)
用于比較兩個值是否嚴格相等,與 (===) 基本類似。
Object.is('q','q') // true Object.is([1],[1]) // false 對象類型要同時比較地址和值 Object.is({q: 1},{q: 1}) //false 對象類型要同時比較地址和值
與 (===) 的區別
// 1. +0 不等于 -0 Object.is(+0, -1) // false +0 === -0 // true // 2. NaN 等于本身 Object.is(NaN, NaN) // true NaN === NaN // false
2.6 數組
數組的創建
-
Array.of()
將參數中所有值作為元素形成數組。
console.log(Array.of(1,2,3,4)) // [1,2,3,4] //參數值可為不同類型 console.log(Array.of(1,'2',true)) // [1, '2', true] //參數為空時返回空數組 console.log(Array.of()) // []
-
Array.from()
將類數組對象或可迭代對象轉化為數組
// 參數為數組,返回與原數組一樣的數組 console.log(Arrays.from([1,2])) // [1, 2] //參數含空位 console.log(Arrays.from([1, ,3])) // [1, undefined, 3]
-
類數組
一個類數組對象必須含有 length 屬性,且元素屬性名必須是數組或可轉換為數值的字符。
let arr = Array.from({ 0: '1', 1: '2', 2: '3', length: 3 }) console.log(arr) //['1','2','3']
-
轉換可迭代對象
// 轉換 map // 轉換 set // 轉換 string let arr = Array.from(map | set | string)
擴展的方法
方法名 | 描述 | 示例 |
---|---|---|
find() | 查找數組中符合條件的元素,若有多個,返回第一個元素 | Array.from(1,2,3).find(x=>x>2) // 3 |
findIndex() | 查找數組中符合條件的元素的索引,若有多個,返回第一個 | Array.from(1,2,3).findIndex(x=>x>2) // 2 |
fill() | 將一定范圍索引的數組元素填充為單個指定的值 | Array.from(1,2,3,4).fill(0,1,2) // [1,0,3,4] |
copyWithin() | 將一定范圍索引的數組元素修改為此數組另一指定范圍索引的元素 | Array.from(1,2,3,4).copyWithin(0,2,4) // [3,4,3,4] |
entries() | 遍歷鍵值對 | N/A |
keys() | 遍歷鍵名 | N/A |
values() | 遍歷鍵值 | N/A |
includes() | 數組是否包含指定值 | N/A |
flat() | 嵌套數組轉一維數組 | [1,[2,3]].flat() // [1,2,3] |
flatMap() | 先對數組中每個元素進行了處理,再對數組執行flat() | [1,[2,3]].flatMap(x=>x*2) // [2,4,6] |
數組緩沖區
數組緩沖區是內存中的一段地址。實際字節數在創建時確定,之后只可修改其中的數據,不可修改大小。
let buffer = ArrayBuffer(10)
console.log(buffer.byteLength) // 10
-
視圖
視圖是用來操作內存的接口。視圖可以操作數組緩沖區或緩沖區字節的子集,并按照其中一種數值數據類型來讀取和寫入數據。
DataView 類型是一種通用的數組緩沖區視圖,其支持所有8種數值型數據類型。
//默認DataView可操作緩沖區的全部內容 let buffer = new ArrayBuffer(10) let dataView = new DataView(buffer) dataView.setInt8(0,1) console.log(dataView.getInt8(0)) //1 //通過設置偏移量和長度指定DataView可操作的字節范圍 let dataView1 = new DataView(buffer, 0, 3) dataView1.setInt8(5,1) // RangeError
定型數組
數組緩沖區特定類型的視圖。可以強制使用特定的數據類型,而不是使用通用的DataView對象來操作數組緩沖區。
let buffer = new ArrayBuffer(10)
let view = new Int8Array(buffer)
console.log(view.byteLength) // 10
length 屬性不可寫,如果嘗試修改這個值,在非嚴格模式下會直接忽略該操作,在嚴格模式下會拋出錯誤。
擴展運算符
- 復制數組
let arr = [1,2],
arr1 = [...arr]
console.log(arr1) //[1,2]
//合并數組
console.log(...[1,2],...[3,4]) // [1,2,3,4]
3 運算符與語句
3.1 函數
-
函數參數的擴展
默認參數
function fn(name, age = 17){ console.log(name + ', ' + age)} fn('Amy', 18) // Amy, 18 fn('Amy') // Amy, 17
a. 使用函數的默認參數時,不允許有同名參數。
b. 只有在未傳遞參數,或者參數為undefined時,才會使用默認參數,null值被認為是有效的值傳遞。
c. 函數參數默認值存在暫時性死區,在函數參數默認值表達式中,還未初始化賦值的參數值無法作為其它參數的默認值。
不定參數
不定參數用來表示不確定的參數個數,形如, ...變量名,由...加上一個具名參數標識符組成。具名參數只能放在參數組的最后,并且有且只有一個不定參數。
function fn(...values){ console.log(values.length)} fn(1, 2) // 2 fn(1,2,3,4) // 4
-
箭頭函數
箭頭函數提供了一種更加簡潔的函數書寫方式。
let f = v => v // 等價于 let f = function(v){ console.log(v)} f(1) // 1
當箭頭函數沒有參數或者有多個參數時,要用()括起來。
當箭頭函數有多行語句,用{} 包裹起來,表示代碼塊,當只有一行語句,并且需要返回結果時,可以省略{} 結果自動返回。
let f = (a,b) => { let result = a + b return result } f(6,2) // 8
當箭頭函數要返回對象的時候,為了區分于代碼塊,要用 () 將對象包裹起來
let f = (id,name) = ({ id: id, name: name}) f(6,2) // {id: 6, name: 2}
沒有 this, super, arguments和new.target 綁定。
箭頭函數體中的 this 對象,是定義函數時的對象,而不是使用函數時對象。
-
適用場景
N/A
-
不適用場景
N/A
3.2 class 類
class(類)作為對象的模板被引入,可以通過class關鍵字定義類。其實class的本質就是function,它可以看作一個語法糖,讓對象原型的寫法更加清晰、更像面向對象編程的語法。
// 匿名類
let Example = class {
constructor(a){
this.a = a
}
}
// 命名類
let Example = class Example{
constructor(a){
this.a = a
}
}
a. 類定義不會被提升,這意味著,必須在訪問前對類進行定義,否則就會報錯。
b. 類中方法不需要 function 關鍵字
c. 方法間不能加分號。
-
類的主體 (以下屬性、方法、實例化,與其它任一編程語言都是相通的,不再作解釋)
屬性
靜態屬性
公共屬性
實例屬性
name屬性
方法
constructor方法
靜態方法
原型方法 實例方法
類的實例化
new
實例化對象
-
decorator
decorator 是一個函數,用來修飾類的行為,在代碼編譯時產生作用。
類修飾
function testable(target){ target.isTestable = true } @testable class Example{} Example.isTestable // true
上面的例子添加的是靜態屬性,若要添加實例屬性,在類的 prototype 上操作即可。
方法修飾
class Example{ @writable sum(a, b) {return a + b} } function writable(target, name, descriptor){ descriptor.writable = false return descriptor }
修飾器執行順序: 由外向內進入,由內向外執行。
-
封裝與繼承
getter / setter
class Example{ constructor(a, b) { this.a = a; // 實例化時調用 set 方法 this.b = b; } get a(){ console.log('getter'); return this.a; } set a(a){ console.log('setter'); this.a = a; // 自身遞歸調用 } } let exam = new Example(1,2); // 不斷輸出 setter ,最終導致 RangeError
extends
class Child extends Father{ ... }
Super
子類constructor方法中必須有super,且必須出現在this之前
class Father { constructor() {} } class Child extends Father { constructor() {} // or // constructor(a) { // this.a = a; // super(); // } } let test = new Child();
不可繼承常規對象
var Father = { // ... } class Child extends Father{ // ... } // Uncaught TypeError: Class extends value #<Object> is not a constructor or null
3.3 ES6 模塊
ES6引入了模塊化,其設計思想是在編譯時就能確定模塊的依賴關系,以及輸入和輸出的變量。
ES6的模塊分為導出(export) @與導入(import) 兩個模塊
-
特點
a. ES6 的模塊自動開啟嚴格模式,不管你有沒有在模塊頭部加上 use strict。
b. 模塊中可以導入和導出各種類型的變量,如函數,對象,字符串,數字,布爾值,類等。
c. 每個模塊都有自己的上下文,每一個模塊內聲明的變量都是局部變量,不會污染全局作用域。
d. 每一個模塊只加載一次(單例),若再去加載同目錄下的同文件,直接從內存中讀取。
-
export 與 import
模塊導入導出各種類型的變量,如字符串,數值,函數,類。
a. 導出的函數聲明與類聲明必須要有名稱(export default 命令另外考慮)。
b. 不僅能導出聲明還能導出引用(函數)。
c. export 命令可以出現在模塊的任何位置,但必須處于模塊頂層。
d.import 命令會提升到整個模塊的頭部,首先執行。
import 命令的特點:
只讀屬性
單例模式
export default 命令:
a. 在一個文件或模塊中,export、import 可以有多個,export default 僅有一個。
b. export default 中的 default 是對應的導出接口變量。
c. 通過 export 方式導出,在導入時要加{ },export default 則不需要。
d. export default 向外暴露的成員,可以使用任意變量來接收。
-
復合使用
export 與 import 可以在同一模塊中使用,使用特點:
a. 可以將導出接口改名,包括default。
b. 復合使用 export 與 import ,也可以導出全部,當前模塊導出的接口會覆蓋繼承導出的。
4 異步編程
4.1 Promise 對象
Promise是異步編程的一種解決方案。從語法上講,Promise是一個對象,從它可以獲取異步操作的消息。
Promise 狀態
Promise 異步操作有三種狀態:pending(進行中), fulfilled(已成功), rejected(已失敗)。除了異步操作的結果,任何其他操作都無法改變這個狀態。
const p1 = new Promise(function(resolve,reject){
resolve('success1');
resolve('success2');
});
const p2 = new Promise(function(resolve,reject){
resolve('success3');
reject('reject');
});
p1.then(function(value){
console.log(value); // success1
});
p2.then(function(value){
console.log(value); // success3
});
狀態的缺點
a. 無法取消 Promise ,一旦新建它就會立即執行,無法中途取消。
b. 如果不設置回調函數,Promise 內部拋出的錯誤,不會反應到外部。
c. 當處于 pending 狀態時,無法得知目前進展到哪一個階段(剛剛開始還是即將完成)。
then 方法
then 方法接收兩個函數作為參數,第一個參數是 Promise 執行成功時的回調,第二個參數是 Promise 執行失敗時的回調,兩個函數只會有一個被調用。
const p = new Promise(function(resolve,reject){
resolve('success');
});
p.then(function(value){
console.log(value);
});
console.log('first');
// first
// success
簡便的Promise鏈式編程最好保持扁平化,不要嵌套Promise。
注意總是返回或終止Promise鏈。
4.2 Generator 函數
ES6新引入的 Generator函數,可以通過yield關鍵字,把函數的執行流掛起,為改變執行流程提供了可能,從而為異步編程提供解決方案。
-
Generator 函數組成
Generator 有兩個區分于普通函數的部分:
a. 一是在function 后面,函數名之前有個 *
b. 函數內部有 yield 表達式。
function* func(){ console.log("one"); yield '1'; console.log("two"); yield '2'; console.log("three"); return '3'; }
-
執行機制
調用 Generator 函數和調用普通函數一樣,在函數名后面加上()即可,但是 Generator 函數不會像普通函數一樣立即執行,而是返回一個指向內部狀態對象的指針,所以要調用遍歷器對象Iterator 的 next 方法,指針就會從函數頭部或者上一次停下來的地方開始執行。
let f = func() f.next() // one // {value: "1", done: false} f.next() // two // {value: "2", done: false} f.next() // three // {value: "3", done: true} f.next() // {value: undefined, done: true}
4.3 Async 函數
async 是 ES7 才有的與異步操作有關的關鍵字,和Promise, Generator 有很大關聯的。
async 函數返回一個 Promise對象,可以使用 then 方法添加回調函數。
async function helloAsync(){
return 'hello async'
}
console.log(helloAsync()) // Promise {<resolved>: 'helloAsync'}
helloAsync().then(v=>{
console.log(v) // hello async
})
async 函數中可能會有 await 表達式,async 函數執行時,如果遇到 await 就會暫停執行,等到觸發的異步操作完成后,恢復async 函數的執行并返回解析值。
await 關鍵字僅在 async function 中有效。
function testAwait(){
return new Promise((resolve) => {
setTimeout(function(){
console.log("testAwait");
resolve();
}, 1000);
});
}
async function helloAsync(){
await testAwait();
console.log("helloAsync");
}
helloAsync();
// testAwait
// helloAsync
await 針對所跟不同表達式的處理方式:
- Promise 對象: await 會暫停執行,等待 Promise 對象 resolve, 然后恢復async函數的執行并返回解析值。
- 非Promise對象: 直接返回對應的值。
總結
N/A