es6學(xué)習(xí)(2019/7/17-7/24)

數(shù)值的擴(kuò)展 date:(2019.07.17)

二進(jìn)制和八進(jìn)制表示法

Number.isFinite(), Number.isNaN()

  Number.isFinite(15); // true
  Number.isFinite(0.8); // true
  Number.isFinite(NaN); // false
  Number.isFinite(Infinity); // false
  Number.isFinite(-Infinity); // false
  Number.isFinite('foo'); // false
  Number.isFinite('15'); // false
  Number.isFinite(true); // false
  Number.isNaN(NaN) // true
  Number.isNaN(15) // false
  Number.isNaN('15') // false
  Number.isNaN(true) // false
  Number.isNaN(9/NaN) // true
  Number.isNaN('true' / 0) // true
  Number.isNaN('true' / 'true') // true
  • 它們與傳統(tǒng)的全局方法isFinite()和isNaN()的區(qū)別在于透罢,傳統(tǒng)方法先調(diào)用Number()將非數(shù)值的值轉(zhuǎn)為數(shù)值,再進(jìn)行判斷丧慈,而這兩個(gè)新方法只對(duì)數(shù)值有效仙蚜,Number.isFinite()對(duì)于非數(shù)值一律返回false, Number.isNaN()只有對(duì)于NaN才返回true怜械,非NaN一律返回false灾而。

Number.parseInt(), Number.parseFloat()

  • ES6 將全局方法parseInt()和parseFloat(),移植到Number對(duì)象上面,行為完全保持不變叫挟,這樣做的目的艰匙,是逐步減少全局性方法,使得語(yǔ)言逐步模塊化
Number.parseInt === parseInt // true
Number.parseFloat === parseFloat // true

Number.isInteger()

  • 用來(lái)判斷一個(gè)數(shù)值是否為整數(shù)
  • JavaScript 內(nèi)部抹恳,整數(shù)和浮點(diǎn)數(shù)采用的是同樣的儲(chǔ)存方法员凝,所以 25 和 25.0 被視為同一個(gè)值
  • 如果參數(shù)不是數(shù)值,Number.isInteger返回false

Number.EPSILON

  • 它表示 1 與大于 1 的最小浮點(diǎn)數(shù)之間的差
  function withinErrorMargin (left, right) {
    return Math.abs(left - right) < Number.EPSILON * Math.pow(2, 2);
  }
  0.1 + 0.2 === 0.3 // false
  withinErrorMargin(0.1 + 0.2, 0.3) // true
  上面的代碼為浮點(diǎn)數(shù)運(yùn)算奋献,部署了一個(gè)誤差檢查函數(shù)

Math 對(duì)象的擴(kuò)展

ES6 在 Math 對(duì)象上新增了 17 個(gè)與數(shù)學(xué)相關(guān)的方法健霹。所有這些方法都是靜態(tài)方法,只能在 Math 對(duì)象上調(diào)用

  • Math.trunc方法用于去除一個(gè)數(shù)的小數(shù)部分瓶蚂,返回整數(shù)部分,對(duì)于非數(shù)值糖埋,Math.trunc內(nèi)部使用Number方法將其先轉(zhuǎn)為數(shù)值,對(duì)于空值和無(wú)法截取整數(shù)的值,返回NaN
Math.trunc = Math.trunc || function(x) {
  return x < 0 ? Math.ceil(x) : Math.floor(x);
};
  • Math.sign方法用來(lái)判斷一個(gè)數(shù)到底是正數(shù)窃这、負(fù)數(shù)瞳别、還是零。對(duì)于非數(shù)值杭攻,會(huì)先將其轉(zhuǎn)換為數(shù)值
它會(huì)返回五種值祟敛。
參數(shù)為正數(shù),返回+1朴上;
參數(shù)為負(fù)數(shù)垒棋,返回-1;
參數(shù)為 0痪宰,返回0叼架;
參數(shù)為-0,返回-0;
其他值衣撬,返回NaN
Math.sign('')  // 0
Math.sign(true)  // +1
Math.sign(false)  // 0
Math.sign(null)  // 0
Math.sign('9')  // +1
Math.sign('foo')  // NaN
Math.sign()  // NaN
Math.sign(undefined) 
  • Math.cbrt方法用于計(jì)算一個(gè)數(shù)的立方根
  • Math.hypot方法返回所有參數(shù)的平方和的平方根

指數(shù)運(yùn)算符

  • ES2016 新增了一個(gè)指數(shù)運(yùn)算符(**)
2 ** 2 // 4
2 ** 3 // 8
  • 指數(shù)運(yùn)算符可以與等號(hào)結(jié)合乖订,形成一個(gè)新的賦值運(yùn)算符(**=)

數(shù)組的擴(kuò)展

1.擴(kuò)展運(yùn)算符

含義

  • 擴(kuò)展運(yùn)算符(spread)是三個(gè)點(diǎn)(...)。它好比 rest 參數(shù)的逆運(yùn)算具练,將一個(gè)數(shù)組轉(zhuǎn)為用逗號(hào)分隔的參數(shù)序列乍构。
    console.log(...[1, 2, 3])
    // 1 2 3
  • 該運(yùn)算符主要用于函數(shù)調(diào)用
    function add(x, y) {
      return x + y;
    }
    const numbers = [4, 38];
    add(...numbers) // 42
  • 擴(kuò)展運(yùn)算符后面還可以放置表達(dá)式
  • 如果擴(kuò)展運(yùn)算符后面是一個(gè)空數(shù)組,則不產(chǎn)生任何效果
  • 只有函數(shù)調(diào)用時(shí)扛点,擴(kuò)展運(yùn)算符才可以放在圓括號(hào)中哥遮,否則會(huì)報(bào)錯(cuò)
  • 替代函數(shù)的 apply 方法

擴(kuò)展運(yùn)算符的應(yīng)用

  • 復(fù)制數(shù)組,只是復(fù)制了指向底層數(shù)據(jù)結(jié)構(gòu)的指針
  • 合并數(shù)組陵究,但是淺拷貝
  • 與解構(gòu)賦值結(jié)合
  // ES5
  a = list[0], rest = list.slice(1)
  // ES6
  [a, ...rest] = list
    • 如果將擴(kuò)展運(yùn)算符用于數(shù)組賦值眠饮,只能放在參數(shù)的最后一位,否則會(huì)報(bào)錯(cuò)
  • 擴(kuò)展運(yùn)算符還可以將字符串轉(zhuǎn)為真正的數(shù)組
  • 實(shí)現(xiàn)了 Iterator 接口的對(duì)象铜邮,都可以用擴(kuò)展運(yùn)算符轉(zhuǎn)為真正的數(shù)組
  • Map 和 Set 結(jié)構(gòu)仪召,Generator 函數(shù)寨蹋,都可以使用擴(kuò)展運(yùn)算符

2.Array.from()

  • Array.from方法用于將兩類對(duì)象轉(zhuǎn)為真正的數(shù)組:類似數(shù)組的對(duì)象(array-like object)和可遍歷(iterable)的對(duì)象(包括 ES6 新增的數(shù)據(jù)結(jié)構(gòu) Set 和 Map)
  • 只要是部署了 Iterator 接口的數(shù)據(jù)結(jié)構(gòu),Array.from都能將其轉(zhuǎn)為數(shù)組
  • 如果參數(shù)是一個(gè)真正的數(shù)組扔茅,Array.from會(huì)返回一個(gè)一模一樣的新數(shù)組
  • Array.from還可以接受第二個(gè)參數(shù)已旧,作用類似于數(shù)組的map方法,用來(lái)對(duì)每個(gè)元素進(jìn)行處理召娜,將處理后的值放入返回的數(shù)組

3.Array.of()

  • Array.of方法用于將一組值运褪,轉(zhuǎn)換為數(shù)組
  • 這個(gè)方法的主要目的,是彌補(bǔ)數(shù)組構(gòu)造函數(shù)Array()的不足玖瘸。因?yàn)閰?shù)個(gè)數(shù)的不同吐句,會(huì)導(dǎo)致Array()的行為有差異。
Array() // []
Array(3) // [, , ,]
Array(3, 11, 8) // [3, 11, 8]
  • Array.of基本上可以用來(lái)替代Array()或new Array()店读,并且不存在由于參數(shù)不同而導(dǎo)致的重載

4.數(shù)組實(shí)例的copyWithin()

  • 在當(dāng)前數(shù)組內(nèi)部,將指定位置的成員復(fù)制到其他位置(會(huì)覆蓋原有成員)攀芯,然后返回當(dāng)前數(shù)組屯断,會(huì)修改當(dāng)前數(shù)組
  • Array.prototype.copyWithin(target, start = 0, end = this.length)
  • 它接受三個(gè)參數(shù):
    • target(必需):從該位置開始替換數(shù)據(jù)。如果為負(fù)值侣诺,表示倒數(shù)殖演。
    • start(可選):從該位置開始讀取數(shù)據(jù),默認(rèn)為 0年鸳。如果為負(fù)值趴久,表示從末尾開始計(jì)算。
    • end(可選):到該位置前停止讀取數(shù)據(jù)搔确,默認(rèn)等于數(shù)組長(zhǎng)度彼棍。如果為負(fù)值,表示從末尾開始計(jì)算膳算。
    • 這三個(gè)參數(shù)都應(yīng)該是數(shù)值座硕,如果不是,會(huì)自動(dòng)轉(zhuǎn)為數(shù)值涕蜂。
    [1, 2, 3, 4, 5].copyWithin(0, 3)
    // [4, 5, 3, 4, 5]

5.數(shù)組實(shí)例的find()和findIndex()

  • 數(shù)組實(shí)例的find方法华匾,用于找出第一個(gè)符合條件的數(shù)組成員。它的參數(shù)是一個(gè)回調(diào)函數(shù)机隙,所有數(shù)組成員依次執(zhí)行該回調(diào)函數(shù)蜘拉,直到找出第一個(gè)返回值為true的成員,然后返回該成員有鹿。如果沒有符合條件的成員旭旭,則返回undefined。
[1, 4, -5, 10].find((n) => n < 0)
// -5
  • find方法的回調(diào)函數(shù)可以接受三個(gè)參數(shù)印颤,依次為當(dāng)前的值您机、當(dāng)前的位置和原數(shù)組
  • 數(shù)組實(shí)例的findIndex方法的用法與find方法非常類似,返回第一個(gè)符合條件的數(shù)組成員的位置,如果所有成員都不符合條件际看,則返回-1
  • find函數(shù)接收了第二個(gè)參數(shù)person對(duì)象咸产,回調(diào)函數(shù)中的this對(duì)象指向person對(duì)象
  • 這兩個(gè)方法都可以發(fā)現(xiàn)NaN,彌補(bǔ)了數(shù)組的indexOf方法的不足

6.數(shù)組實(shí)例的fill()

  • fill方法使用給定值仲闽,填充一個(gè)數(shù)組
  • fill方法用于空數(shù)組的初始化非常方便脑溢。數(shù)組中已有的元素,會(huì)被全部抹去赖欣。
  • fill方法還可以接受第二個(gè)和第三個(gè)參數(shù)屑彻,用于指定填充的起始位置和結(jié)束位置

7.數(shù)組實(shí)例的entries(),keys()和values()

  • 用于遍歷數(shù)組
  • 可以用for...of循環(huán)進(jìn)行遍歷,唯一的區(qū)別是keys()是對(duì)鍵名的遍歷顶吮、values()是對(duì)鍵值的遍歷社牲,entries()是對(duì)鍵值對(duì)的遍歷

8.數(shù)組實(shí)例的includes()

  • 方法返回一個(gè)布爾值,表示某個(gè)數(shù)組是否包含給定的值悴了,該方法的第二個(gè)參數(shù)表示搜索的起始位置

9.數(shù)組實(shí)例的flat(),flatMap()

  • 數(shù)組的成員有時(shí)還是數(shù)組搏恤,Array.prototype.flat()用于將嵌套的數(shù)組“拉平”,變成一維的數(shù)組湃交,該方法返回一個(gè)新數(shù)組熟空,對(duì)原數(shù)據(jù)沒有影響
  • 默認(rèn)只會(huì)“拉平”一層,如果想要“拉平”多層的嵌套數(shù)組搞莺,可以將flat()方法的參數(shù)寫成一個(gè)整數(shù)息罗,表示想要拉平的層數(shù),默認(rèn)為1
    [1, 2, [3, [4, 5]]].flat()
    // [1, 2, 3, [4, 5]]
    [1, 2, [3, [4, 5]]].flat(2)
    // [1, 2, 3, 4, 5]
    
  • 如果不管有多少層嵌套才沧,都要轉(zhuǎn)成一維數(shù)組迈喉,可以用Infinity關(guān)鍵字作為參數(shù)
  • 如果原數(shù)組有空位,flat()方法會(huì)跳過空位温圆。
    [1, 2, , 4, 5].flat()
    // [1, 2, 4, 5]
    
  • 遍歷函數(shù)返回的是一個(gè)雙層的數(shù)組弊添,但是默認(rèn)只能展開一層,因此flatMap()返回的還是一個(gè)嵌套數(shù)組

10.數(shù)組的空位

  • 空位不是undefined捌木,一個(gè)位置的值等于undefined油坝,依然是有值的,空位是沒有任何值,in運(yùn)算符可以說(shuō)明這一點(diǎn)
  • Array.from方法會(huì)將數(shù)組的空位刨裆,轉(zhuǎn)為undefined
  • 擴(kuò)展運(yùn)算符(...)也會(huì)將空位轉(zhuǎn)為undefined
  • copyWithin()會(huì)連空位一起拷貝
  • fill()會(huì)將空位視為正常的數(shù)組位置
  • for...of循環(huán)也會(huì)遍歷空位
  • entries()澈圈、keys()、values()帆啃、find()和findIndex()會(huì)將空位處理成undefined

TDD作業(yè)

Number API

<p align="center" style="display:inline-block">
<p>Number->Number.isInteger()</p>
<img src="./img/TDD-Number.isInteger.png" height="150">
</p>
<p align="center" style="display:inline-block">
<p> Number->Number.isNaN()</p>
<img src="./img/TDD-Number.isNaN.png" height="150">
</p>

Array API

<p align="center" style="display:inline-block">
<p> Array->Array.from()</p>
<img src="./img/TDD-Array.from.png" height="150">
</p>
<p align="center" style="display:inline-block">
<p> Array->Array.from()</p>
<img src="./img/TDD-Array.from.png" height="150">
</p>
<p align="center" style="display:inline-block">
<p> Array->Array.of()</p>
<img src="./img/TDD-Array.of.png" height="150">
</p>
<p align="center" style="display:inline-block">
<p> Array->Array.fill()</p>
<img src="./img/TDD-Array.fill.png" height="150">
</p>
<p align="center" style="display:inline-block">
<p> Array->Array.find()</p>
<img src="./img/TDD-Array.find.png" height="150">
</p>
<p align="center" style="display:inline-block">
<p> Array->Array.findIndex()</p>
<img src="./img/TDD-Array.findIndex.png" height="150">
</p>
<p align="center" style="display:inline-block">
<p> Array->Array.entries()</p>
<img src="./img/TDD-Array.entries.png" height="150">
</p>
<p align="center" style="display:inline-block">
<p> Array->Array.keys()</p>
<img src="./img/TDD-Array.keys.png" height="150">
</p>
<p align="center" style="display:inline-block">
<p> Array->Array.values()</p>
<img src="./img/TDD-Array.values.png" height="150">
</p>
圖區(qū):


TDD-Number.isInteger.png

TDD-Number.isNaN.png

TDD-Array.values.png
TDD-Array.entries.png
TDD-Array.fill.png
TDD-Array.find.png
TDD-Array.findIndex.png
TDD-Array.from.png
TDD-Array.keys.png
TDD-Array.of.png

date:(2019.07.18)

let const

  1. for循環(huán)的計(jì)數(shù)器很適合let命令
  2. let聲明不存在變量提升
  3. let const聲明變量瞬女,暫存性死區(qū)(TDZ)
  • 暫時(shí)性死區(qū)的本質(zhì)就是,只要一進(jìn)入當(dāng)前作用域努潘,所要使用的變量就已經(jīng)存在了诽偷,但是不可獲取坤学,只有等到聲明變量的那一行代碼出現(xiàn),才可以獲取和使用該變量报慕。
  1. 不允許出現(xiàn)重復(fù)聲明

塊級(jí)作用域

  1. 為什么需要塊級(jí)作用域深浮?
  • 內(nèi)層變量可能會(huì)覆蓋外層變量
  • 用來(lái)計(jì)數(shù)的循環(huán)變量泄露為全局變量
  1. es6的塊級(jí)作用域
  • ES6 允許塊級(jí)作用域的任意嵌套
  • 使得立即執(zhí)行函數(shù)不那么必要了
  1. 塊級(jí)作用域與函數(shù)聲明
  • ES5 規(guī)定,函數(shù)只能在頂層作用域和函數(shù)作用域之中聲明眠冈,不能在塊級(jí)作用域聲明飞苇,瀏覽器沒有遵守這個(gè)規(guī)定
  • ES6 的塊級(jí)作用域必須有大括號(hào)

const命令

  1. 基本用法
  • const聲明一個(gè)只讀的常量。一旦聲明蜗顽,常量的值就不能改變
  • const一旦聲明變量布卡,就必須立即初始化
  • 只在聲明所在的塊級(jí)作用域內(nèi)有效
  • 聲明的常量也是不提升,同樣存在暫時(shí)性死區(qū)雇盖,只能在聲明的位置后面使用
  • 不可重復(fù)聲明
  1. 本質(zhì)
  • const實(shí)際上保證的忿等,并不是變量的值不得改動(dòng),而是變量指向的那個(gè)內(nèi)存地址所保存的數(shù)據(jù)不得改動(dòng)
  • 可以用const什么{}和[]且賦值不會(huì)報(bào)錯(cuò)
  • 想將對(duì)象凍結(jié)崔挖,應(yīng)該使用Object.freeze方法
  1. ES6 聲明變量的六種方法
  • var这弧、function、let虚汛、const、import皇帮、class卷哩,ES6 一共有 6 種聲明變量的方法。

頂層對(duì)象的屬性

  • 頂層對(duì)象属拾,在瀏覽器環(huán)境指的是window對(duì)象将谊,在 Node 指的是global對(duì)象。ES5 之中渐白,頂層對(duì)象的屬性與全局變量是等價(jià)的
  • var命令和function命令聲明的全局變量尊浓,依舊是頂層對(duì)象的屬性
  • let命令、const命令纯衍、class命令聲明的全局變量栋齿,不屬于頂層對(duì)象的屬性。也就是說(shuō)襟诸,從 ES6 開始瓦堵,全局變量將逐步與頂層對(duì)象的屬性脫鉤

globalThis對(duì)象

  • JavaScript 語(yǔ)言存在一個(gè)頂層對(duì)象,它提供全局環(huán)境歌亲,但是菇用,頂層對(duì)象在各種實(shí)現(xiàn)里面是不統(tǒng)一的
  • 瀏覽器里面,頂層對(duì)象是window陷揪,但 Node 和 Web Worker 沒有window
  • 瀏覽器和 Web Worker 里面惋鸥,self也指向頂層對(duì)象杂穷,但是 Node 沒有self
  • Node 里面,頂層對(duì)象是global卦绣,但其他環(huán)境都不支持

字符串的擴(kuò)展

1.字符Unicode表示法

  • ES6 加強(qiáng)了對(duì) Unicode 的支持耐量,允許采用\uxxxx形式表示一個(gè)字符,其中xxxx表示字符的 Unicode 碼點(diǎn)迎卤。
  "\u0061"
  // "a"
  • JavaScript 共有 6 種方法可以表示一個(gè)字符拴鸵。
  '\z' === 'z'  // true
  '\172' === 'z' // true
  '\x7A' === 'z' // true
  '\u007A' === 'z' // true
  '\u{7A}' === 'z' // true

2.字符串的遍歷器接口

  • ES6 為字符串添加了遍歷器接口,使得字符串可以被for...of循環(huán)遍歷
  for (let codePoint of 'foo') {
    console.log(codePoint)
  }
  // "f"
  // "o"
  // "o"

3.直接輸入U(xiǎn)+2028和U+2029

  • javaScript 字符串允許直接輸入字符蜗搔,以及輸入字符的轉(zhuǎn)義形式

    '中' === '\u4e2d' // true

  • javaScript 規(guī)定有5個(gè)字符劲藐,不能在字符串里面直接使用,只能使用轉(zhuǎn)義形式樟凄。

U+005C:反斜杠(reverse solidus)
U+000D:回車(carriage return)
U+2028:行分隔符(line separator)
U+2029:段分隔符(paragraph separator)
U+000A:換行符(line feed)

4.JSON.stringify()的改造

5.模板字符串

  • 模板字符串(template string)是增強(qiáng)版的字符串聘芜,用反引號(hào)(`)標(biāo)識(shí),它可以當(dāng)作普通字符串使用缝龄,也可以用來(lái)定義多行字符串汰现,或者在字符串中嵌入變量
// 普通字符串
`In JavaScript '\n' is a line-feed.`

// 多行字符串
`In JavaScript this is
 not legal.`

console.log(`string text line 1
string text line 2`);

// 字符串中嵌入變量
let name = "Bob", time = "today";
`Hello ${name}, how are you ${time}?`
  • 模板字符串表示多行字符串,所有的空格和縮進(jìn)都會(huì)被保留在輸出之中叔壤,使用trim方法消除它
  • 模板字符串中嵌入變量瞎饲,需要將變量名寫在${}之中,大括號(hào)內(nèi)部可以放入任意的 JavaScript 表達(dá)式炼绘,可以進(jìn)行運(yùn)算嗅战,以及引用對(duì)象屬性
let x = 1;
let y = 2;
`${x} + ${y} = ${x + y}`
// "1 + 2 = 3"
`${x} + ${y * 2} = ${x + y * 2}`
// "1 + 4 = 5"
let obj = {x: 1, y: 2};
`${obj.x + obj.y}`
// "3"
  • 模板字符串之中還能調(diào)用函數(shù)
function fn() {
  return "Hello World";
}

`foo ${fn()} bar`
  • 模板字符串甚至還能嵌套

6.實(shí)例:模板編譯

  • 使用<%...%>放置 JavaScript 代碼,使用<%= ... %>輸出 JavaScript 表達(dá)式

7.標(biāo)簽?zāi)0?/h3>
  • 模板字符串的功能俺亮,不僅僅是上面這些驮捍。它可以緊跟在一個(gè)函數(shù)名后面,該函數(shù)將被調(diào)用來(lái)處理這個(gè)模板字符串脚曾。這被稱為“標(biāo)簽?zāi)0濉惫δ?/li>
  • 標(biāo)簽?zāi)0迤鋵?shí)不是模板东且,而是函數(shù)調(diào)用的一種特殊形式”炯ィ“標(biāo)簽”指的就是函數(shù)珊泳,緊跟在后面的模板字符串就是它的參數(shù)
  • 如果模板字符里面有變量,就不是簡(jiǎn)單的調(diào)用了拷沸,而是會(huì)將模板字符串先處理成多個(gè)參數(shù)旨椒,再調(diào)用函數(shù)
    let a = 5;
    let b = 10;

    tag`Hello ${ a + b } world ${ a * b }`;
    // 等同于
    tag(['Hello ', ' world ', ''], 15, 50);

8.模板字符串的限制

函數(shù)的擴(kuò)展

1.函數(shù)參數(shù)的默認(rèn)值

基本用法

  • ES6 允許為函數(shù)的參數(shù)設(shè)置默認(rèn)值,即直接寫在參數(shù)定義的后面
  • 參數(shù)變量是默認(rèn)聲明的堵漱,所以不能用let或const再次聲明
  function foo(x = 5) {
    let x = 1; // error
    const x = 2; // error
  }
  • 使用參數(shù)默認(rèn)值時(shí)综慎,函數(shù)不能有同名參數(shù)
  • 一個(gè)容易忽略的地方是,參數(shù)默認(rèn)值不是傳值的勤庐,而是每次都重新計(jì)算默認(rèn)值表達(dá)式的值示惊。也就是說(shuō)好港,參數(shù)默認(rèn)值是惰性求值的

與解構(gòu)賦值默認(rèn)值結(jié)合使用

  • 參數(shù)默認(rèn)值可以與解構(gòu)賦值的默認(rèn)值,結(jié)合起來(lái)使用
  function foo({x, y = 5} = {}) {
    console.log(x, y);
  }

  foo() // undefined 5
  • 上面代碼指定米罚,如果沒有提供參數(shù)钧汹,函數(shù)foo的參數(shù)默認(rèn)為一個(gè)空對(duì)象

參數(shù)默認(rèn)值的位置

  • 通常情況下,定義了默認(rèn)值的參數(shù)录择,應(yīng)該是函數(shù)的尾參數(shù)拔莱。因?yàn)檫@樣比較容易看出來(lái),到底省略了哪些參數(shù)隘竭,如果非尾部的參數(shù)設(shè)置默認(rèn)值塘秦,實(shí)際上這個(gè)參數(shù)是沒法省略的
  • 如果傳入undefined,將觸發(fā)該參數(shù)等于默認(rèn)值动看,null則沒有這個(gè)效果

函數(shù)的 length 屬性

  • 指定了默認(rèn)值以后尊剔,函數(shù)的length屬性,將返回沒有指定默認(rèn)值的參數(shù)個(gè)數(shù)菱皆。也就是說(shuō)须误,指定了默認(rèn)值后,length屬性將失真

    (function(...args) {}).length // 0

  • 如果設(shè)置了默認(rèn)值的參數(shù)不是尾參數(shù)仇轻,那么length屬性也不再計(jì)入后面的參數(shù)了

    (function(a, b=1, c){}).length
    1
    (function(a, b, c=1){}).length
    2
    (function(a, b, c){}).length
    3

作用域

  • 一旦設(shè)置了參數(shù)的默認(rèn)值京痢,函數(shù)進(jìn)行聲明初始化時(shí),參數(shù)會(huì)形成一個(gè)單獨(dú)的作用域
  • 如果參數(shù)的默認(rèn)值是一個(gè)函數(shù)篷店,該函數(shù)的作用域也遵守這個(gè)規(guī)則

應(yīng)用

  • 利用參數(shù)默認(rèn)值祭椰,可以指定某一個(gè)參數(shù)不得省略,如果省略就拋出一個(gè)錯(cuò)誤
function throwIfMissing() {
  throw new Error('Missing parameter');
}
function foo(mustBeProvided = throwIfMissing()) {
  return mustBeProvided;
}
foo()
// Error: Missing parameter
  • 參數(shù)的默認(rèn)值不是在定義時(shí)執(zhí)行船庇,而是在運(yùn)行時(shí)執(zhí)行

rest參數(shù)

  • ES6 引入 rest 參數(shù)(形式為...變量名),用于獲取函數(shù)的多余參數(shù)侣监,這樣就不需要使用arguments對(duì)象了鸭轮。rest 參數(shù)搭配的變量是一個(gè)數(shù)組,該變量將多余的參數(shù)放入數(shù)組中
  • rest 參數(shù)之后不能再有其他參數(shù)
  • 函數(shù)的length屬性橄霉,不包括 rest 參數(shù)

嚴(yán)格模式

  • ES2016 規(guī)定只要函數(shù)參數(shù)使用了默認(rèn)值窃爷、解構(gòu)賦值、或者擴(kuò)展運(yùn)算符姓蜂,那么函數(shù)內(nèi)部就不能顯式設(shè)定為嚴(yán)格模式
  • 兩種方法可以規(guī)避這種限制按厘。第一種是設(shè)定全局性的嚴(yán)格模式
  • 第二種是把函數(shù)包在一個(gè)無(wú)參數(shù)的立即執(zhí)行函數(shù)里面

name 屬性

  • 函數(shù)的name屬性,返回該函數(shù)的函數(shù)名
  • 變量f等于一個(gè)匿名函數(shù)钱慢,ES5 和 ES6 的name屬性返回的值不一樣
  • 如果將一個(gè)具名函數(shù)賦值給一個(gè)變量,則 ES5 和 ES6 的name屬性都返回這個(gè)具名函數(shù)原本的名字。
  • Function構(gòu)造函數(shù)返回的函數(shù)實(shí)例嚣潜,name屬性的值為anonymous
  • bind返回的函數(shù),name屬性值會(huì)加上bound前綴

箭頭函數(shù)

  • =>

  • 如果箭頭函數(shù)不需要參數(shù)或需要多個(gè)參數(shù)草描,就使用一個(gè)圓括號(hào)代表參數(shù)部分

  • 如果箭頭函數(shù)的代碼塊部分多于一條語(yǔ)句,就要使用大括號(hào)將它們括起來(lái)策严,并且使用return語(yǔ)句返回

  • 如果箭頭函數(shù)直接返回一個(gè)對(duì)象穗慕,必須在對(duì)象外面加上括號(hào),否則會(huì)報(bào)錯(cuò)

  • 如果箭頭函數(shù)只有一行語(yǔ)句妻导,且不需要返回值逛绵,可以采用下面的寫法,就不用寫大括號(hào)了

    let fn = () => void doesNotReturn();

  • 箭頭函數(shù)可以與變量解構(gòu)結(jié)合使用

  • 箭頭函數(shù)的一個(gè)用處是簡(jiǎn)化回調(diào)函數(shù)

使用注意點(diǎn)

  • 箭頭函數(shù)有幾個(gè)使用注意點(diǎn)倔韭。

    • 函數(shù)體內(nèi)的this對(duì)象术浪,就是定義時(shí)所在的對(duì)象,而不是使用時(shí)所在的對(duì)象狐肢。
    • 不可以當(dāng)作構(gòu)造函數(shù)添吗,也就是說(shuō),不可以使用new命令份名,否則會(huì)拋出一個(gè)錯(cuò)誤碟联。
    • 不可以使用arguments對(duì)象,該對(duì)象在函數(shù)體內(nèi)不存在僵腺。如果要用鲤孵,可以用 rest 參數(shù)代替。
    • 不可以使用yield命令辰如,因此箭頭函數(shù)不能用作 Generator 函數(shù)普监。
  • 上面四點(diǎn)中,第一點(diǎn)尤其值得注意琉兜。this對(duì)象的指向是可變的凯正,但是在箭頭函數(shù)中,它是固定的

  • 除了this豌蟋,以下三個(gè)變量在箭頭函數(shù)之中也是不存在的廊散,指向外層函數(shù)的對(duì)應(yīng)變量:arguments、super梧疲、new.target

  • 由于箭頭函數(shù)沒有自己的this允睹,所以當(dāng)然也就不能用call()、apply()幌氮、bind()這些方法去改變this的指向

不適用場(chǎng)合

  • 第一個(gè)場(chǎng)合是定義對(duì)象的方法缭受,且該方法內(nèi)部包括this
  • 第二個(gè)場(chǎng)合是需要?jiǎng)討B(tài)this的時(shí)候,也不應(yīng)使用箭頭函數(shù)

嵌套的箭頭函數(shù)

尾調(diào)用優(yōu)化

  • 尾調(diào)用(Tail Call)是函數(shù)式編程的一個(gè)重要概念该互,指某個(gè)函數(shù)的最后一步是調(diào)用另一個(gè)函數(shù)
  • 以下三種情況米者,都不屬于尾調(diào)用
    // 情況一
    function f(x){
      let y = g(x);
      return y;
    }
    // 情況二
    function f(x){
      return g(x) + 1;
    }
    // 情況三
    function f(x){
      g(x);
    }
  • 尾調(diào)用不一定出現(xiàn)在函數(shù)尾部,只要是最后一步操作即可

尾遞歸

函數(shù)參數(shù)的尾逗號(hào)

  • ES2017 允許函數(shù)的最后一個(gè)參數(shù)有尾逗號(hào)

Unicode

<p align="center" style="display:inline-block">
<p> Unicode->In strings</p>
<img src="./img/TDD-unicode.png" height="150">
</p>

Template strings

<p align="center" style="display:inline-block">
<p> Template strings->basics</p>
<img src="./img/TDD-templateString-basics.png" height="150">
</p>
<p align="center" style="display:inline-block">
<p> Template strings->Multiline</p>
<img src="./img/TDD-template-multiline.png" height="150">
</p>
<p align="center" style="display:inline-block">
<p> Template strings->Tagged template strings</p>
<img src="./img/TDD-templateTagged.png" height="150">
</p>
<p align="center" style="display:inline-block">
<p> Template strings->raw</p>
<img src="./img/TDD-template-String.raw.png" height="150">
</p>

Symbol

<p align="center" style="display:inline-block">
<p> Symbol->Symbol.for</p>
<img src="./img/TDD-symbol.for.png" height="150">
</p>
<p align="center" style="display:inline-block">
<p> Symbol->Symbol.keyfor</p>
<img src="./img/TDD-symbol.keyfor.png" height="150">
</p>
<p align="center" style="display:inline-block">
<p> Symbol->Basics</p>
<img src="./img/TDD-symbol-basics.png" height="150">
</p>

Object API

<p align="center" style="display:inline-block">
<p> Symbol->Object.is()</p>
<img src="./img/TDD-Object.is.png" height="150">
</p>

Modules

<p align="center" style="display:inline-block">
<p> Modules->import</p>
<img src="./img/TDD-module-import.png" height="150">
</p>

Default Parameters

<p align="center" style="display:inline-block">
<p> Default Parameters->Basics</p>
<img src="./img/TDD-DefaultParameters.png" height="150">
</p>

Spread operator

<p align="center" style="display:inline-block">
<p> Spread operator->With Array</p>
<img src="./img/TDD-spreaddestructuring.png" height="150">
</p>
<p align="center" style="display:inline-block">
<p> Spread operator->With String</p>
<img src="./img/TDD-spread-string.png" height="150">
</p>

Rest operator

<p align="center" style="display:inline-block">
<p> Rest operator->As parameter
</p>
<img src="./img/TDD-rest-parameter.png" height="150">
</p>
<p align="center" style="display:inline-block">
<p> Rest operator->With destructuring</p>
<img src="./img/TDD-spread-string.png" height="150">
</p>
圖片區(qū)域:


TDD-unicode.png
TDD-arrowbasis.png
TDD-arrowFunction-binding.png
TDD-blockscope-const.png
TDD-blockscope-let.png
TDD-DefaultParameters.png
TDD-module-import.png
TDD-Object.is.png
TDD-rest-parameter.png
TDD-spreaddestructuring.png
TDD-spread-string.png
TDD-symbol.for.png
TDD-symbol.keyfor.png
TDD-symbol-basics.png
TDD-template-multiline.png
TDD-template-String.raw.png
TDD-templateString-basics.png
TDD-templateTagged.png

date(07.22)

變量的解構(gòu)賦值

數(shù)組的解構(gòu)賦值

  1. 基本用法
  • 按照一定模式宇智,從數(shù)組和對(duì)象中提取值塘雳,對(duì)變量進(jìn)行賦值陆盘,這被稱為解構(gòu)
  • 本質(zhì)上,這種寫法屬于“模式匹配”败明,只要等號(hào)兩邊的模式相同隘马,左邊的變量就會(huì)被賦予對(duì)應(yīng)的值
  • 解構(gòu)不成功,變量的值就等于undefined
  • 不完全解構(gòu)妻顶,即等號(hào)左邊的模式酸员,只匹配一部分的等號(hào)右邊的數(shù)組。這種情況下讳嘱,解構(gòu)依然可以成功
  • 如果等號(hào)的右邊不是數(shù)組(或者嚴(yán)格地說(shuō)幔嗦,不是可遍歷的結(jié)構(gòu)),那么將會(huì)報(bào)錯(cuò)
let [foo] = 1;
let [foo] = false;
let [foo] = NaN;
let [foo] = undefined;
let [foo] = null;
let [foo] = {};
  • 事實(shí)上沥潭,只要某種數(shù)據(jù)結(jié)構(gòu)具有 Iterator 接口邀泉,都可以采用數(shù)組形式的解構(gòu)賦值
  1. 默認(rèn)值
  • ES6 內(nèi)部使用嚴(yán)格相等運(yùn)算符(===),判斷一個(gè)位置是否有值钝鸽。所以汇恤,只有當(dāng)一個(gè)數(shù)組成員嚴(yán)格等于undefined,默認(rèn)值才會(huì)生效
  • 默認(rèn)值是一個(gè)表達(dá)式拔恰,那么這個(gè)表達(dá)式是惰性求值
  • 默認(rèn)值可以引用解構(gòu)賦值的其他變量因谎,但該變量必須已經(jīng)聲明

對(duì)象的解構(gòu)賦值

  1. 簡(jiǎn)介
  • 對(duì)象的解構(gòu)與數(shù)組有一個(gè)重要的不同。數(shù)組的元素是按次序排列的颜懊,變量的取值由它的位置決定财岔;而對(duì)象的屬性沒有次序,變量必須與屬性同名河爹,才能取到正確的值
  • 如果解構(gòu)失敗匠璧,變量的值等于undefined
  • 將Math對(duì)象的對(duì)數(shù)、正弦咸这、余弦三個(gè)方法夷恍,賦值到對(duì)應(yīng)的變量上,使用起來(lái)就會(huì)方便很多
let { log, sin, cos } = Math;
  • 如果變量名與屬性名不一致炊苫,必須寫成下面這樣
let obj = { first: 'hello', last: 'world' };
let { first: f, last: l } = obj;
f // 'hello'
l // 'world'
  • 對(duì)象的解構(gòu)賦值可以取到繼承的屬性
  • 解構(gòu)也可以用于嵌套結(jié)構(gòu)的對(duì)象
let obj = {
  p: [
    'Hello',
    { y: 'World' }
  ]
};
let { p: [x, { y }] } = obj;
x // "Hello"
y // "World"
  • 注意裁厅,這時(shí)p是模式冰沙,不是變量侨艾,因此不會(huì)被賦值。如果p也要作為變量賦值拓挥,可以寫成下面這樣唠梨。
let obj = {
  p: [
    'Hello',
    { y: 'World' }
  ]
};
let { p, p: [x, { y }] } = obj;
x // "Hello"
y // "World"
p // ["Hello", {y: "World"}]
  1. 默認(rèn)值
  • 對(duì)象的解構(gòu)也可以指定默認(rèn)值
  • 默認(rèn)值生效的條件是,對(duì)象的屬性值嚴(yán)格等于undefined
  1. 注意點(diǎn)
  • 如果要將一個(gè)已經(jīng)聲明的變量用于解構(gòu)賦值侥啤,必須非常小心
  • 解構(gòu)賦值允許等號(hào)左邊的模式之中当叭,不放置任何變量名茬故。因此,可以寫出非常古怪的賦值表達(dá)式
  • 由于數(shù)組本質(zhì)是特殊的對(duì)象蚁鳖,因此可以對(duì)數(shù)組進(jìn)行對(duì)象屬性的解構(gòu)
let arr = [1, 2, 3];
let {0 : first, [arr.length - 1] : last} = arr;//方括號(hào)這種寫法磺芭,屬于“屬性名表達(dá)式”
first // 1
last // 3
  1. 字符串的解構(gòu)賦值
  • 字符串也可以解構(gòu)賦值。這是因?yàn)榇藭r(shí)醉箕,字符串被轉(zhuǎn)換成了一個(gè)類似數(shù)組的對(duì)象
const [a, b, c, d, e] = 'hello';
a // "h"
b // "e"
c // "l"
d // "l"
e // "o"
  • 類似數(shù)組的對(duì)象都有一個(gè)length屬性钾腺,因此還可以對(duì)這個(gè)屬性解構(gòu)賦值
let {length : len} = 'hello';
len // 5
  1. 數(shù)值和布爾值的解構(gòu)賦值
  • 解構(gòu)賦值的規(guī)則是,只要等號(hào)右邊的值不是對(duì)象或數(shù)組讥裤,就先將其轉(zhuǎn)為對(duì)象放棒。由于undefined和null無(wú)法轉(zhuǎn)為對(duì)象,所以對(duì)它們進(jìn)行解構(gòu)賦值己英,都會(huì)報(bào)錯(cuò)
  1. 函數(shù)參數(shù)的解構(gòu)賦值
  • undefined就會(huì)觸發(fā)函數(shù)參數(shù)的默認(rèn)值
  1. 圓括號(hào)問題
  • es6規(guī)則:只要有可能導(dǎo)致解構(gòu)的歧義间螟,就不得使用圓括號(hào);阮一峰建議只要有可能损肛,就不要在模式中放置圓括號(hào)
  • 不能使用圓括號(hào)的情況
    1. 變量聲明語(yǔ)句
// 全部報(bào)錯(cuò)
let [(a)] = [1];
let {x: (c)} = {};
let ({x: c}) = {};
let {(x: c)} = {};
let {(x): c} = {};

let { o: ({ p: p }) } = { o: { p: 2 } };
    1. 函數(shù)參數(shù)
// 報(bào)錯(cuò)
function f([(z)]) { return z; }
// 報(bào)錯(cuò)
function f([z,(x)]) { return x; }
    1. 賦值語(yǔ)句的模式
  • 可以使用圓括號(hào)的情況
    • 賦值語(yǔ)句的非模式部分厢破,可以使用圓括號(hào)
  1. 用途
    1. 交換變量的值
    1. 從函數(shù)返回多個(gè)值
    1. 函數(shù)參數(shù)的定義
    1. JSON數(shù)據(jù)的提取
    1. 函數(shù)參數(shù)的默認(rèn)值
    1. 遍歷map數(shù)組
      • 任何部署了 Iterator 接口的對(duì)象,都可以用for...of循環(huán)遍歷荧关。Map 結(jié)構(gòu)原生支持 Iterator 接口溉奕,配合變量的解構(gòu)賦值,獲取鍵名和鍵值就非常方便忍啤。
              const map = new Map();
              map.set('first', 'hello');
              map.set('second', 'world');

              for (let [key, value] of map) {
                console.log(key + " is " + value);
              }
              // first is hello
              // second is world
      • 如果只想獲取鍵名加勤,或者只想獲取鍵值,可以寫成下面這樣同波。
              // 獲取鍵名
              for (let [key] of map) {
                // ...
              }
              // 獲取鍵值
              for (let [,value] of map) {
                // ...
              }
    1. 輸入模塊的指定方法

class表達(dá)式
與函數(shù)一樣鳄梅,類也可以使用表達(dá)式的形式定義

const myClass = new Me{
    getClassName(){
        return Me.name;
    }
}
set
var s = new set();
s.add()

不會(huì)添加重復(fù)值
Set函數(shù)可以接受一個(gè)數(shù)組(或者具有 iterable 接口的其他數(shù)據(jù)結(jié)構(gòu))作為參數(shù),用來(lái)初始化
set可以可以去重(包括NaN)
兩個(gè)對(duì)象總是不相等的
Set結(jié)構(gòu)實(shí)例有一下屬性:
Set.prototype.constructor:構(gòu)造函數(shù)未檩,默認(rèn)就是Set函數(shù)戴尸。
Set.prototype.size:返回Set實(shí)例的成員總數(shù)。
Set實(shí)例分為兩大類冤狡,操作方法和遍歷方法

Set.prototype.add(value):添加某個(gè)值孙蒙,返回 Set 結(jié)構(gòu)本身。
Set.prototype.delete(value):刪除某個(gè)值悲雳,返回一個(gè)布爾值挎峦,表示刪除是否成功。
Set.prototype.has(value):返回一個(gè)布爾值合瓢,表示該值是否為Set的成員坦胶。
Set.prototype.clear():清除所有成員,沒有返回值。

Array.from方法可以將 Set 結(jié)構(gòu)轉(zhuǎn)為數(shù)組
數(shù)組去重:Array.from(new Set(array))

Set.prototype.keys():返回鍵名的遍歷器
Set.prototype.values():返回鍵值的遍歷器
Set.prototype.entries():返回鍵值對(duì)的遍歷器
Set.prototype.forEach():使用回調(diào)函數(shù)遍歷每個(gè)成員

for of;map;filter;
因此使用 Set 可以很容易地實(shí)現(xiàn)并集(Union)顿苇、交集(Intersect)和差集(Difference)峭咒。

let a = new Set([1, 2, 3]);
let b = new Set([4, 3, 2]);

// 并集

let union = new Set([...a, ...b]);
// Set {1, 2, 3, 4}

// 交集

let intersect = new Set([...a].filter(x => b.has(x)));
// set {2, 3}

// 差集

let difference = new Set([...a].filter(x => !b.has(x)));
// Set {1}

map

ES6 提供了 Map 數(shù)據(jù)結(jié)構(gòu)。它類似于對(duì)象纪岁,也是鍵值對(duì)的集合凑队,但是“鍵”的范圍不限于字符串,各種類型的值(包括對(duì)象)都可以當(dāng)作鍵

Set和Map都可以用來(lái)生成新的 Map

size 屬性

Map.prototype.set(key, value)
Map.prototype.get(key)
Map.prototype.has(key)
Map.prototype.delete(key)
Map.prototype.clear()
Map.prototype.keys():返回鍵名的遍歷器幔翰。
Map.prototype.values():返回鍵值的遍歷器顽决。
Map.prototype.entries():返回所有成員的遍歷器。
Map.prototype.forEach():遍歷 Map 的所有成員

iterator

1. Iterator(遍歷器)的概念

  1. 遍歷器(Iterator)就是這樣一種機(jī)制导匣。它是一種接口才菠,為各種不同的數(shù)據(jù)結(jié)構(gòu)提供統(tǒng)一的訪問機(jī)制。任何數(shù)據(jù)結(jié)構(gòu)只要部署 Iterator 接口贡定,就可以完成遍歷操作(即依次處理該數(shù)據(jù)結(jié)構(gòu)的所有成員)
  2. Iterator 的作用有三個(gè):一是為各種數(shù)據(jù)結(jié)構(gòu)赋访,提供一個(gè)統(tǒng)一的、簡(jiǎn)便的訪問接口缓待;二是使得數(shù)據(jù)結(jié)構(gòu)的成員能夠按某種次序排列蚓耽;三是 ES6 創(chuàng)造了一種新的遍歷命令for...of循環(huán),Iterator 接口主要供for...of消費(fèi)
  3. Iterator 的遍歷過程是這樣的
    (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é)束位置择卦。
    每一次調(diào)用next方法,都會(huì)返回?cái)?shù)據(jù)結(jié)構(gòu)的當(dāng)前成員的信息郎嫁。具體來(lái)說(shuō)秉继,就是返回一個(gè)包含value和done兩個(gè)屬性的對(duì)象。其中泽铛,value屬性是當(dāng)前成員的值尚辑,done屬性是一個(gè)布爾值,表示遍歷是否結(jié)束厚宰。

2. 默認(rèn) Iterator 接口

3. 調(diào)用 Iterator 接口的場(chǎng)合

4. 字符串的 Iterator 接口

5. Iterator 接口與 Generator 函數(shù)

6. 遍歷器對(duì)象的 return()腌巾,throw()

7. for...of 循環(huán)

promise

1.Promise的含義

  1. Promise 是異步編程的一種解決方案,比傳統(tǒng)的解決方案——回調(diào)函數(shù)和事件——更合理和更強(qiáng)大
  2. 所謂Promise铲觉,簡(jiǎn)單說(shuō)就是一個(gè)容器澈蝙,里面保存著某個(gè)未來(lái)才會(huì)結(jié)束的事件(通常是一個(gè)異步操作)的結(jié)果。從語(yǔ)法上說(shuō)撵幽,Promise 是一個(gè)對(duì)象灯荧,從它可以獲取異步操作的消息。Promise 提供統(tǒng)一的 API盐杂,各種異步操作都可以用同樣的方法進(jìn)行處理
  3. Promise對(duì)象有以下兩個(gè)特點(diǎn)逗载。
    • 對(duì)象的狀態(tài)不受外界影響。Promise對(duì)象代表一個(gè)異步操作链烈,有三種狀態(tài):pending(進(jìn)行中)厉斟、fulfilled(已成功)和rejected(已失敗)强衡。只有異步操作的結(jié)果擦秽,可以決定當(dāng)前是哪一種狀態(tài),任何其他操作都無(wú)法改變這個(gè)狀態(tài)漩勤。這也是Promise這個(gè)名字的由來(lái)感挥,它的英語(yǔ)意思就是“承諾”,表示其他手段無(wú)法改變越败。
    • 一旦狀態(tài)改變触幼,就不會(huì)再變,任何時(shí)候都可以得到這個(gè)結(jié)果究飞。Promise對(duì)象的狀態(tài)改變置谦,只有兩種可能:從pending變?yōu)閒ulfilled和從pending變?yōu)閞ejected。只要這兩種情況發(fā)生亿傅,狀態(tài)就凝固了霉祸,不會(huì)再變了,會(huì)一直保持這個(gè)結(jié)果袱蜡,這時(shí)就稱為 resolved(已定型)丝蹭。如果改變已經(jīng)發(fā)生了,你再對(duì)Promise對(duì)象添加回調(diào)函數(shù)坪蚁,也會(huì)立即得到這個(gè)結(jié)果奔穿。這與事件(Event)完全不同,事件的特點(diǎn)是敏晤,如果你錯(cuò)過了它贱田,再去監(jiān)聽,是得不到結(jié)果的嘴脾。
    • Promise也有一些缺點(diǎn)男摧。首先蔬墩,無(wú)法取消Promise,一旦新建它就會(huì)立即執(zhí)行耗拓,無(wú)法中途取消拇颅。其次,如果不設(shè)置回調(diào)函數(shù)乔询,Promise內(nèi)部拋出的錯(cuò)誤樟插,不會(huì)反應(yīng)到外部。第三竿刁,當(dāng)處于pending狀態(tài)時(shí)黄锤,無(wú)法得知目前進(jìn)展到哪一個(gè)階段

2.基本用法

const promise = new Promise(function(resolve, reject) {
  // ... some code

  if (/* 異步操作成功 */){
    resolve(value);
  } else {
    reject(error);
  }
});
  1. Promise構(gòu)造函數(shù)接受一個(gè)函數(shù)作為參數(shù),該函數(shù)的兩個(gè)參數(shù)分別是resolve和reject食拜。它們是兩個(gè)函數(shù)鸵熟,由 JavaScript 引擎提供,不用自己部署
  2. resolve函數(shù)的作用是负甸,將Promise對(duì)象的狀態(tài)從“未完成”變?yōu)椤俺晒Α保磸?pending 變?yōu)?resolved)旅赢,在異步操作成功時(shí)調(diào)用,并將異步操作的結(jié)果惑惶,作為參數(shù)傳遞出去
  3. reject函數(shù)的作用是煮盼,將Promise對(duì)象的狀態(tài)從“未完成”變?yōu)椤笆 保磸?pending 變?yōu)?rejected),在異步操作失敗時(shí)調(diào)用带污,并將異步操作報(bào)出的錯(cuò)誤僵控,作為參數(shù)傳遞出去
  4. Promise實(shí)例生成以后,可以用then方法分別指定resolved狀態(tài)和rejected狀態(tài)的回調(diào)函數(shù)
promise.then(function(value) {
  // success
}, function(error) {
  // failure
});
  • then方法可以接受兩個(gè)回調(diào)函數(shù)作為參數(shù)鱼冀。第一個(gè)回調(diào)函數(shù)是Promise對(duì)象的狀態(tài)變?yōu)閞esolved時(shí)調(diào)用报破,第二個(gè)回調(diào)函數(shù)是Promise對(duì)象的狀態(tài)變?yōu)閞ejected時(shí)調(diào)用。其中千绪,第二個(gè)函數(shù)是可選的充易,不一定要提供。這兩個(gè)函數(shù)都接受Promise對(duì)象傳出的值作為參數(shù)
  1. Promise 新建后就會(huì)立即執(zhí)行荸型。
let promise = new Promise(function(resolve, reject) {
  console.log('Promise');
  resolve();
});
promise.then(function() {
  console.log('resolved.');
});
console.log('Hi!');
// Promise
// Hi!
// resolved
  • Promise 新建后立即執(zhí)行盹靴,所以首先輸出的是Promise。然后瑞妇,then方法指定的回調(diào)函數(shù)稿静,將在當(dāng)前腳本所有同步任務(wù)執(zhí)行完才會(huì)執(zhí)行,所以resolved最后輸出
  1. resolve函數(shù)的參數(shù)除了正常的值以外辕狰,還可能是另一個(gè) Promise
const p1 = new Promise(function (resolve, reject) {
  // ...
});
const p2 = new Promise(function (resolve, reject) {
  // ...
  resolve(p1);
})
  • p1和p2都是 Promise 的實(shí)例改备,但是p2的resolve方法將p1作為參數(shù),即一個(gè)異步操作的結(jié)果是返回另一個(gè)異步操作
  • 注意蔓倍,這時(shí)p1的狀態(tài)就會(huì)傳遞給p2悬钳,也就是說(shuō)盐捷,p1的狀態(tài)決定了p2的狀態(tài)。如果p1的狀態(tài)是pending默勾,那么p2的回調(diào)函數(shù)就會(huì)等待p1的狀態(tài)改變碉渡;如果p1的狀態(tài)已經(jīng)是resolved或者rejected,那么p2的回調(diào)函數(shù)將會(huì)立刻執(zhí)行

3.Promise.prototype.then()

  1. Promise 實(shí)例具有then方法,是定義在原型對(duì)象Promise.prototype上的,它的作用是為 Promise 實(shí)例添加狀態(tài)改變時(shí)的回調(diào)函數(shù)灾测。then方法的第一個(gè)參數(shù)是resolved狀態(tài)的回調(diào)函數(shù),第二個(gè)參數(shù)(可選)是rejected狀態(tài)的回調(diào)函數(shù)垦巴,then方法返回的是一個(gè)新的Promise實(shí)例(注意媳搪,不是原來(lái)那個(gè)Promise實(shí)例),因此可以采用鏈?zhǔn)綄懛ㄖ栊磘hen方法后面再調(diào)用另一個(gè)then方法

4.Promise.prototype.catch()

  1. Promise.prototype.catch方法是.then(null, rejection)或.then(undefined, rejection)的別名秦爆,用于指定發(fā)生錯(cuò)誤時(shí)的回調(diào)函數(shù)
p.then((val) => console.log('fulfilled:', val))
  .catch((err) => console.log('rejected', err));
// 等同于
p.then((val) => console.log('fulfilled:', val))
  .then(null, (err) => console.log("rejected:", err));
const promise = new Promise(function(resolve, reject) {
  throw new Error('test');
});
//等同于
promise.catch(function(error) {
  console.log(error);
});
// Error: test
// 寫法一
const promise = new Promise(function(resolve, reject) {
  try {
    throw new Error('test');
  } catch(e) {
    reject(e);
  }
});
promise.catch(function(error) {
  console.log(error);
});

// 寫法二
const promise = new Promise(function(resolve, reject) {
  reject(new Error('test'));
});
promise.catch(function(error) {
  console.log(error);
});
  • 比較上面兩種寫法,可以發(fā)現(xiàn)reject方法的作用憔披,等同于拋出錯(cuò)誤等限。
  1. 如果 Promise 狀態(tài)已經(jīng)變成resolved,再拋出錯(cuò)誤是無(wú)效的
  2. Promise 對(duì)象的錯(cuò)誤具有“冒泡”性質(zhì)芬膝,會(huì)一直向后傳遞望门,直到被捕獲為止。也就是說(shuō)锰霜,錯(cuò)誤總是會(huì)被下一個(gè)catch語(yǔ)句捕獲
  3. 一般來(lái)說(shuō)筹误,不要在then方法里面定義 Reject 狀態(tài)的回調(diào)函數(shù)(即then的第二個(gè)參數(shù)),總是使用catch方法
// bad
promise
  .then(function(data) {
    // success
  }, function(err) {
    // error
  });

// good
promise
  .then(function(data) { //cb
    // success
  })
  .catch(function(err) {
    // error
  });
  • 第二種寫法要好于第一種寫法癣缅,理由是第二種寫法可以捕獲前面then方法執(zhí)行中的錯(cuò)誤厨剪,也更接近同步的寫法(try/catch)。因此友存,建議總是使用catch方法祷膳,而不使用then方法的第二個(gè)參數(shù)

5.Promise.prototype.finally()

  1. inally方法用于指定不管 Promise 對(duì)象最后狀態(tài)如何,都會(huì)執(zhí)行的操作
promise
.then(result => {···})
.catch(error => {···})
.finally(() => {···});
  • 不管promise最后的狀態(tài)屡立,在執(zhí)行完then或catch指定的回調(diào)函數(shù)以后直晨,都會(huì)執(zhí)行finally方法指定的回調(diào)函數(shù)
  1. finally方法的回調(diào)函數(shù)不接受任何參數(shù),這意味著沒有辦法知道膨俐,前面的 Promise 狀態(tài)到底是fulfilled還是rejected抡秆。這表明,finally方法里面的操作吟策,應(yīng)該是與狀態(tài)無(wú)關(guān)的儒士,不依賴于 Promise 的執(zhí)行結(jié)果

6.Promise.all()

  1. Promise.all方法用于將多個(gè) Promise 實(shí)例,包裝成一個(gè)新的 Promise 實(shí)例
  • const p = Promise.all([p1, p2, p3]);
  • Promise.all方法接受一個(gè)數(shù)組作為參數(shù)檩坚,p1着撩、p2诅福、p3都是 Promise 實(shí)例,如果不是拖叙,就會(huì)先調(diào)用下面講到的Promise.resolve方法氓润,將參數(shù)轉(zhuǎn)為 Promise 實(shí)例,再進(jìn)一步處理薯鳍。(Promise.all方法的參數(shù)可以不是數(shù)組咖气,但必須具有 Iterator 接口,且返回的每個(gè)成員都是 Promise 實(shí)例挖滤。)
  • p的狀態(tài)由p1崩溪、p2、p3決定斩松,分成兩種情況伶唯。
  • (1)只有p1、p2惧盹、p3的狀態(tài)都變成fulfilled乳幸,p的狀態(tài)才會(huì)變成fulfilled,此時(shí)p1钧椰、p2粹断、p3的返回值組成一個(gè)數(shù)組,傳遞給p的回調(diào)函數(shù)嫡霞;(2)只要p1姿染、p2、p3之中有一個(gè)被rejected秒际,p的狀態(tài)就變成rejected悬赏,此時(shí)第一個(gè)被reject的實(shí)例的返回值,會(huì)傳遞給p的回調(diào)函數(shù)

7.Promise.race()

  • Promise.race方法同樣是將多個(gè) Promise 實(shí)例娄徊,包裝成一個(gè)新的 Promise 實(shí)例
  • 上面代碼中闽颇,只要p1、p2寄锐、p3之中有一個(gè)實(shí)例率先改變狀態(tài)兵多,p的狀態(tài)就跟著改變。那個(gè)率先改變的 Promise 實(shí)例的返回值橄仆,就傳遞給p的回調(diào)函數(shù)

8.Promise.resolve()

  1. 有時(shí)需要將現(xiàn)有對(duì)象轉(zhuǎn)為 Promise 對(duì)象剩膘,Promise.resolve方法就起到這個(gè)作用
  2. Promise.resolve方法的參數(shù)分成四種情況。
  • 參數(shù)是一個(gè) Promise 實(shí)例

    • 如果參數(shù)是 Promise 實(shí)例盆顾,那么Promise.resolve將不做任何修改怠褐、原封不動(dòng)地返回這個(gè)實(shí)例。
  • 參數(shù)是一個(gè)thenable對(duì)象

    • thenable對(duì)象指的是具有then方法的對(duì)象您宪,比如下面這個(gè)對(duì)象奈懒。
let thenable = {
  then: function(resolve, reject) {
    resolve(42);
  }
};
    • Promise.resolve方法會(huì)將這個(gè)對(duì)象轉(zhuǎn)為 Promise 對(duì)象奠涌,然后就立即執(zhí)行thenable對(duì)象的then方法。
  • 參數(shù)不是具有then方法的對(duì)象磷杏,或根本就不是對(duì)象
    • 如果參數(shù)是一個(gè)原始值溜畅,或者是一個(gè)不具有then方法的對(duì)象,則Promise.resolve方法返回一個(gè)新的 Promise 對(duì)象极祸,狀態(tài)為resolved慈格。
  • 不帶有任何參數(shù)
    • Promise.resolve()方法允許調(diào)用時(shí)不帶參數(shù),直接返回一個(gè)resolved狀態(tài)的 Promise 對(duì)象遥金,所以浴捆,如果希望得到一個(gè) Promise 對(duì)象,比較方便的方法就是直接調(diào)用Promise.resolve()方法汰规。

9.Promise.reject()

  1. Promise.reject(reason)方法也會(huì)返回一個(gè)新的 Promise 實(shí)例汤功,該實(shí)例的狀態(tài)為rejected
  • 注意物邑,Promise.reject()方法的參數(shù)溜哮,會(huì)原封不動(dòng)地作為reject的理由,變成后續(xù)方法的參數(shù)

10.應(yīng)用

  1. 異步加載圖片
function loadImageAsync(url) {
  return new Promise(function(resolve, reject) {
    const image = new Image();

    image.onload = function() {
      resolve(image);
    };

    image.onerror = function() {
      reject(new Error('Could not load image at ' + url));
    };

    image.src = url;
  });
}
  1. Ajax 操作
const getJSON = function(url) {
  const promise = new Promise(function(resolve, reject){
    const handler = function() {
      if (this.readyState !== 4) {
        return;
      }
      if (this.status === 200) {
        resolve(this.response);
      } else {
        reject(new Error(this.statusText));
      }
    };
    const client = new XMLHttpRequest();
    client.open("GET", url);
    client.onreadystatechange = handler;
    client.responseType = "json";
    client.setRequestHeader("Accept", "application/json");
    client.send();
  });
  return promise;
};
getJSON("/posts.json").then(function(json) {
  console.log('Contents: ' + json);
}, function(error) {
  console.error('出錯(cuò)了', error);
});
  • getJSON是對(duì) XMLHttpRequest 對(duì)象的封裝色解,用于發(fā)出一個(gè)針對(duì) JSON 數(shù)據(jù)的 HTTP 請(qǐng)求茂嗓,并且返回一個(gè)Promise對(duì)象。需要注意的是科阎,在getJSON內(nèi)部述吸,resolve函數(shù)和reject函數(shù)調(diào)用時(shí),都帶有參數(shù)锣笨。如果調(diào)用resolve函數(shù)和reject函數(shù)時(shí)帶有參數(shù)蝌矛,那么它們的參數(shù)會(huì)被傳遞給回調(diào)函數(shù)。reject函數(shù)的參數(shù)通常是Error對(duì)象的實(shí)例错英,表示拋出的錯(cuò)誤

11.Promise.try()

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
禁止轉(zhuǎn)載入撒,如需轉(zhuǎn)載請(qǐng)通過簡(jiǎn)信或評(píng)論聯(lián)系作者。
  • 序言:七十年代末椭岩,一起剝皮案震驚了整個(gè)濱河市茅逮,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌判哥,老刑警劉巖献雅,帶你破解...
    沈念sama閱讀 219,188評(píng)論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異塌计,居然都是意外死亡挺身,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,464評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門锌仅,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)瞒渠,“玉大人良蒸,你說(shuō)我怎么就攤上這事∥榫粒” “怎么了嫩痰?”我有些...
    開封第一講書人閱讀 165,562評(píng)論 0 356
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)窍箍。 經(jīng)常有香客問我串纺,道長(zhǎng),這世上最難降的妖魔是什么椰棘? 我笑而不...
    開封第一講書人閱讀 58,893評(píng)論 1 295
  • 正文 為了忘掉前任纺棺,我火速辦了婚禮,結(jié)果婚禮上邪狞,老公的妹妹穿的比我還像新娘祷蝌。我一直安慰自己,他們只是感情好帆卓,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,917評(píng)論 6 392
  • 文/花漫 我一把揭開白布巨朦。 她就那樣靜靜地躺著,像睡著了一般剑令。 火紅的嫁衣襯著肌膚如雪糊啡。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,708評(píng)論 1 305
  • 那天吁津,我揣著相機(jī)與錄音棚蓄,去河邊找鬼。 笑死碍脏,一個(gè)胖子當(dāng)著我的面吹牛梭依,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播典尾,決...
    沈念sama閱讀 40,430評(píng)論 3 420
  • 文/蒼蘭香墨 我猛地睜開眼役拴,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了急黎?” 一聲冷哼從身側(cè)響起扎狱,我...
    開封第一講書人閱讀 39,342評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎勃教,沒想到半個(gè)月后淤击,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,801評(píng)論 1 317
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡故源,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,976評(píng)論 3 337
  • 正文 我和宋清朗相戀三年污抬,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 40,115評(píng)論 1 351
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡印机,死狀恐怖矢腻,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情射赛,我是刑警寧澤多柑,帶...
    沈念sama閱讀 35,804評(píng)論 5 346
  • 正文 年R本政府宣布,位于F島的核電站楣责,受9級(jí)特大地震影響竣灌,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜秆麸,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,458評(píng)論 3 331
  • 文/蒙蒙 一初嘹、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧沮趣,春花似錦屯烦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,008評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至育叁,卻和暖如春迅脐,著一層夾襖步出監(jiān)牢的瞬間芍殖,已是汗流浹背豪嗽。 一陣腳步聲響...
    開封第一講書人閱讀 33,135評(píng)論 1 272
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留豌骏,地道東北人趁啸。 一個(gè)月前我還...
    沈念sama閱讀 48,365評(píng)論 3 373
  • 正文 我出身青樓阿逃,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子播掷,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,055評(píng)論 2 355

推薦閱讀更多精彩內(nèi)容

  • [TOC] 參考阮一峰的ECMAScript 6 入門參考深入淺出ES6 let和const let和const都...
    郭子web閱讀 1,781評(píng)論 0 1
  • 第一章:塊級(jí)作用域綁定 塊級(jí)聲明 1.var聲明及變量提升機(jī)制:在函數(shù)作用域或者全局作用域中通過關(guān)鍵字var聲明的...
    BeADre_wang閱讀 839評(píng)論 0 0
  • 本文為阮一峰大神的《ECMAScript 6 入門》的個(gè)人版提純! babel babel負(fù)責(zé)將JS高級(jí)語(yǔ)法轉(zhuǎn)義帖努,...
    Devildi已被占用閱讀 1,985評(píng)論 0 4
  • let ES6新增的用于變量聲明的關(guān)鍵字 通過let聲明的變量幔亥,不允許重復(fù)聲明 不支持變量聲明預(yù)解析,let變量洒琢,...
    年過古稀的Coder閱讀 296評(píng)論 0 1
  • 第5章 引用類型(返回首頁(yè)) 本章內(nèi)容 使用對(duì)象 創(chuàng)建并操作數(shù)組 理解基本的JavaScript類型 使用基本類型...
    大學(xué)一百閱讀 3,237評(píng)論 0 4