ECMA6所有知識(shí)點(diǎn)大概筆記

ECMAScript和JavaScript的關(guān)系是,前者是后者的規(guī)格,后者是前者的一種實(shí)現(xiàn)
初學(xué)者一開始學(xué)習(xí)JavaScript,其實(shí)就是在學(xué)3.0版的語(yǔ)法。


Node.js是JavaScript語(yǔ)言的服務(wù)器運(yùn)行環(huán)境,對(duì)ES6的支持度比瀏覽器更高。通過(guò)Node,可以體驗(yàn)更多ES6的特性。建議使用版
本管理工具nvm,來(lái)安裝Node,因?yàn)榭梢宰杂汕袚Q版本。不過(guò), nvm 不支持Windows系統(tǒng),如果你使用Windows系統(tǒng),下面的
操作可以改用nvmw或nvm-windows代替。


Babel是一個(gè)廣泛使用的ES6轉(zhuǎn)碼器,可以將ES6代碼轉(zhuǎn)為ES5代碼,從而在現(xiàn)有環(huán)境執(zhí)行


ES6新增了 let 命令,用來(lái)聲明變量。它的用法類似于 var ,但是所聲明的變量,只在 let 命令所在的代碼塊內(nèi)有效

let 不像 var 那樣會(huì)發(fā)生“變量提升”現(xiàn)象。所以,變量一定要在聲明后使用,否則報(bào)錯(cuò)。

只要塊級(jí)作用域內(nèi)存在 let 命令,它所聲明的變量就“綁定”(binding)這個(gè)區(qū)域,ES6明確規(guī)定,如果區(qū)塊中存在 let 和 const 命令,這個(gè)區(qū)塊對(duì)這些命令聲明的變量,從一開始就形成了封閉作用域。凡是
在聲明之前就使用這些變量,就會(huì)報(bào)錯(cuò)。

let不允許在相同作用域內(nèi),重復(fù)聲明同一個(gè)變量


為什么需要塊級(jí)作用域?ES5只有全局作用域和函數(shù)作用域,沒有塊級(jí)作用域,這帶來(lái)很多不合理的場(chǎng)景
第一種場(chǎng)景,內(nèi)層變量可能會(huì)覆蓋外層變量
第二種場(chǎng)景,用來(lái)計(jì)數(shù)的循環(huán)變量泄露為全局變量。
let 實(shí)際上為JavaScript新增了塊級(jí)作用域

ES5存在函數(shù)提升,不管會(huì)
不會(huì)進(jìn)入 if 代碼塊,函數(shù)聲明都會(huì)提升到當(dāng)前作用域的頂部,得到執(zhí)行
而ES6支持塊級(jí)作用域,不管會(huì)不會(huì)進(jìn)入if代碼
塊,其內(nèi)部聲明的函數(shù)皆不會(huì)影響到作用域的外部。


const 聲明一個(gè)只讀的常量。一旦聲明,常量的值就不能改變。
const聲明的變量不得改變值,這意味著,const一旦聲明變量,就必須立即初始化,不能留到以后賦值。
const的作用域與let命令相同:只在聲明所在的塊級(jí)作用域內(nèi)有效,也是不提升,存在暫時(shí)性死區(qū),不可重復(fù)聲明
對(duì)于復(fù)合類型的變量(對(duì)象),變量名不指向數(shù)據(jù),而是指向數(shù)據(jù)所在的地址,不可變的只是這個(gè)地址,但對(duì)象本身是可變的,所以依然可以為其添加新屬性


ES5只有兩種聲明變量的方法: var 命令和 function 命令。ES6除了添加 let 和 const 命令另外
兩種聲明變量的方法: import 命令和 class 命令。所以,ES6一共有6種聲明變量的方法。


全局對(duì)象是最頂層的對(duì)象,在瀏覽器環(huán)境指的是 window 對(duì)象,在Node.js指的是 global 對(duì)象
var 命令和 function 命令聲明的全局變量,依舊是全局對(duì)象的屬性;另一方面規(guī)定,let 命令、 const 命令、 class 命令聲明的全局變量,不屬于全局對(duì)象的屬性。


數(shù)組解構(gòu)的元素是按次序排列的,變量的取值由它的位置決定;而對(duì)象的屬性沒有次序,變量必須與屬性同名,才能取到正確的值。
對(duì)象的解構(gòu)賦值的內(nèi)部機(jī)制,是先找到同名屬性,然后再賦給對(duì)應(yīng)的變量。真正被賦值的是后者,而不是前者。

解構(gòu)賦值的規(guī)則是,只要等號(hào)右邊的值不是對(duì)象,就先將其轉(zhuǎn)為對(duì)象,由于 undefined 和 null 無(wú)法轉(zhuǎn)為對(duì)象,所以對(duì)它們
進(jìn)行解構(gòu)賦值,都會(huì)報(bào)錯(cuò)。

解構(gòu)賦值對(duì)提取JSON對(duì)象中的數(shù)據(jù),函數(shù)參數(shù)的默認(rèn)值,尤其有用。


avaScript內(nèi)部,字符以UTF-16的格式儲(chǔ)存,每個(gè)字符固定為2個(gè)字節(jié),對(duì)于那些需要4個(gè)字節(jié)儲(chǔ)存的字符(Unicode碼點(diǎn)大于
0xFFFF的字符),JavaScript會(huì)認(rèn)為它們是兩個(gè)字符。


JavaScript只有 indexOf 方法,可以用來(lái)確定一個(gè)字符串是否包含在另一個(gè)字符串中,ES6又提供了三種新方法
includes():返回布爾值,表示是否找到了參數(shù)字符串
startsWith():返回布爾值,表示參數(shù)字符串是否在源字符串的頭部
endsWith():返回布爾值,表示參數(shù)字符串是否在源字符串的尾部
這三個(gè)方法都支持第二個(gè)參數(shù),表示開始搜索的位置


repeat 方法返回一個(gè)新字符串,表示將原字符串重復(fù) n 次
padStart 和 padEnd 字符串補(bǔ)全長(zhǎng)度的功能,一共接受兩個(gè)參數(shù),第一個(gè)參數(shù)用來(lái)指定字符串的最小長(zhǎng)度,第二個(gè)參數(shù)是用來(lái)補(bǔ)全的
字符串。


模板字符串(template string)是增強(qiáng)版的字符串,用反引號(hào)(`)標(biāo)識(shí)。它可以當(dāng)作普通字符串使用,也可以用來(lái)定義多行字符
串,或者在字符串中嵌入變量。模板字符串中嵌入變量,需要將變量名寫在 {} 之中。{}如果大括號(hào)中的值不是字符串,將按照一般的規(guī)則轉(zhuǎn)為字符串。比如,大括號(hào)中是一個(gè)對(duì)象,將默認(rèn)調(diào)用對(duì)象的 toString 方
法。大括號(hào)內(nèi)部,就是執(zhí)行JavaScript代碼,因此如果大括號(hào)內(nèi)部是一個(gè)字符串,將會(huì)原樣輸出

ES6還為原生的String對(duì)象,提供了一個(gè) raw 方法。String.raw 方法,往往用來(lái)充當(dāng)模板字符串的處理函數(shù),返回一個(gè)斜杠都被轉(zhuǎn)義(即斜杠前面再加一個(gè)斜杠)的字符串,對(duì)
應(yīng)于替換變量后的模板字符串。


Number.isFinite()用來(lái)檢查一個(gè)數(shù)值是否為有限的(finite),即不是Infinity。
Number.isNaN()用來(lái)檢查一個(gè)值是否為NaN。
Number.isFinite()對(duì)于非數(shù)值一律返回false, Number.isNaN()只有對(duì)于NaN才返回true,非NaN一律返回false。
ES6 將全局方法parseInt()和parseFloat(),移植到Number對(duì)象上面
Number.isInteger()用來(lái)判斷一個(gè)數(shù)值是否為整數(shù)。
Math.trunc方法用于去除一個(gè)數(shù)的小數(shù)部分,返回整數(shù)部分。
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。

ES6 允許為函數(shù)的參數(shù)設(shè)置默認(rèn)值,即直接寫在參數(shù)定義的后面function Point(x = 0, y = 0)
參數(shù)變量是默認(rèn)聲明的,所以不能用let或const再次聲明。參數(shù)默認(rèn)值是惰性求值的
undefined,結(jié)果觸發(fā)了默認(rèn)值,null,就沒有觸發(fā)默認(rèn)值。

這是因?yàn)閘ength屬性的含義是,該函數(shù)預(yù)期傳入的參數(shù)個(gè)數(shù)。某個(gè)參數(shù)指定默認(rèn)值以后,預(yù)期傳入的參數(shù)個(gè)數(shù)就不包括這個(gè)參數(shù)了。如果設(shè)置了默認(rèn)值的參數(shù)不是尾參數(shù),那么length屬性也不再計(jì)入后面的參數(shù)了。

一旦設(shè)置了參數(shù)的默認(rèn)值,函數(shù)進(jìn)行聲明初始化時(shí),參數(shù)會(huì)形成一個(gè)單獨(dú)的作用域

ES6 引入 rest

參數(shù)(形式為...變量名),用于獲取函數(shù)的多余參數(shù),這樣就不需要使用arguments對(duì)象了。rest 參數(shù)搭配的變量是一個(gè)數(shù)組,該變量將多余的參數(shù)放入數(shù)組中。
注意,rest 參數(shù)之后不能再有其他參數(shù)(即只能是最后一個(gè)參數(shù)),否則會(huì)報(bào)錯(cuò)。函數(shù)的length屬性,不包括 rest 參數(shù)


ES6 允許使用“箭頭”(=>)定義函數(shù)。箭頭函數(shù)和普通函數(shù)。前者的this綁定定義時(shí)所在的作用域,后者的this指向運(yùn)行時(shí)所在的作用域。this指向的固定化,并不是因?yàn)榧^函數(shù)內(nèi)部有綁定this的機(jī)制,實(shí)際原因是箭頭函數(shù)根本沒有自己的this,導(dǎo)致內(nèi)部的this就是外層代碼塊的this。正是因?yàn)樗鼪]有this,所以也就不能用作構(gòu)造函數(shù)。除了this,以下三個(gè)變量在箭頭函數(shù)之中也是不存在的,指向外層函數(shù)的對(duì)應(yīng)變量:arguments、super、new.target。


ES6 中只要使用尾遞歸,就不會(huì)發(fā)生棧溢出,相對(duì)節(jié)省內(nèi)存。這將大大節(jié)省內(nèi)存。這就是“尾調(diào)用優(yōu)化”的意義。ES6 的尾調(diào)用優(yōu)化只在嚴(yán)格模式下開啟,正常模式是無(wú)效的。


擴(kuò)展運(yùn)算符(spread)是三個(gè)點(diǎn)(...)。它好比 rest 參數(shù)的逆運(yùn)算,將一個(gè)數(shù)組轉(zhuǎn)為用逗號(hào)分隔的參數(shù)序列。容易和rest混淆,兩個(gè)不是一個(gè)東西。

function f(v, w, x, y, z) { }
const args = [0, 1];
f(-1, ...args, 2, ...[3]);

1.由于擴(kuò)展運(yùn)算符可以展開數(shù)組,所以不再需要apply方法,將數(shù)組轉(zhuǎn)為函數(shù)的參數(shù)了。

2.數(shù)組是復(fù)合的數(shù)據(jù)類型,直接復(fù)制的話,只是復(fù)制了指向底層數(shù)據(jù)結(jié)構(gòu)的指針,而不是克隆一個(gè)全新的數(shù)組。擴(kuò)展運(yùn)算符提供了復(fù)制數(shù)組的簡(jiǎn)便寫法。

const a1 = [1, 2];
// 寫法一
const a2 = [...a1];
// 寫法二
const [...a2] = a1;
3.合并數(shù)組
// ES5
[1, 2].concat(more)
// ES6
[1, 2, ...more]

4.擴(kuò)展運(yùn)算符可以與解構(gòu)賦值結(jié)合起來(lái),用于生成數(shù)組。如果將擴(kuò)展運(yùn)算符用于數(shù)組賦值,只能放在參數(shù)的最后一位,否則會(huì)報(bào)錯(cuò)。
const [...butLast, last] = [1, 2, 3, 4, 5];
// 報(bào)錯(cuò)

5.擴(kuò)展運(yùn)算符還可以將字符串轉(zhuǎn)為真正的數(shù)組。
[...'hello']
// [ "h", "e", "l", "l", "o" ]

擴(kuò)展運(yùn)算符內(nèi)部調(diào)用的是數(shù)據(jù)結(jié)構(gòu)的 Iterator 接口,因此只要具有 Iterator 接口的對(duì)象,都可以使用擴(kuò)展運(yùn)算符,如果對(duì)沒有 Iterator 接口的對(duì)象,使用擴(kuò)展運(yùn)算符,將會(huì)報(bào)錯(cuò)。


Array.from方法用于將兩類對(duì)象轉(zhuǎn)為真正的數(shù)組,擴(kuò)展運(yùn)算符背后調(diào)用的是遍歷器接口(Symbol.iterator),如果一個(gè)對(duì)象沒有部署這個(gè)接口,就無(wú)法轉(zhuǎn)換。Array.from方法還支持類似數(shù)組的對(duì)象。所謂類似數(shù)組的對(duì)象,本質(zhì)特征只有一點(diǎn),即必須有l(wèi)ength屬性。因此,任何有l(wèi)ength屬性的對(duì)象,都可以通過(guò)Array.from方法轉(zhuǎn)為數(shù)組,而此時(shí)擴(kuò)展運(yùn)算符就無(wú)法轉(zhuǎn)換。

Array.from還可以接受第二個(gè)參數(shù),作用類似于數(shù)組的map方法,用來(lái)對(duì)每個(gè)元素進(jìn)行處理,將處理后的值放入返回的數(shù)組。第三個(gè)參數(shù),用來(lái)綁定this。


Array.of方法用于將一組值,轉(zhuǎn)換為數(shù)組。
Array.of(3, 11, 8) // [3,11,8]
Array.of基本上可以用來(lái)替代Array()或new Array(),并且不存在由于參數(shù)不同而導(dǎo)致的重載。它的行為非常統(tǒng)一。


數(shù)組實(shí)例的copyWithin方法,在當(dāng)前數(shù)組內(nèi)部,將指定位置的成員復(fù)制到其他位置(會(huì)覆蓋原有成員),然后返回當(dāng)前數(shù)組。也就是說(shuō),使用這個(gè)方法,會(huì)修改當(dāng)前數(shù)組。

[1, 2, 3, 4, 5].copyWithin(0, 3)
// [4, 5, 3, 4, 5]

上面代碼表示將從 3 號(hào)位直到數(shù)組結(jié)束的成員(4 和 5),復(fù)制到從 0 號(hào)位開始的位置,結(jié)果覆蓋了原來(lái)的 1 和 2。


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

[1, 4, -5, 10].find((n) => n < 0)
// -5

數(shù)組實(shí)例的findIndex方法的用法與find方法非常類似,返回第一個(gè)符合條件的數(shù)組成員的位置,如果所有成員都不符合條件,則返回-1。
這兩個(gè)方法都可以發(fā)現(xiàn)NaN,彌補(bǔ)了數(shù)組的indexOf方法的不足。


ES6 提供三個(gè)新的方法——entries(),keys()和values()——用于遍歷數(shù)組。keys()是對(duì)鍵名的遍歷、values()是對(duì)鍵值的遍歷,entries()是對(duì)鍵值對(duì)的遍歷。


數(shù)組實(shí)例的 includes(),沒有該方法之前,我們通常使用數(shù)組的indexOf方法,檢查是否包含某個(gè)值。indexOf方法有兩個(gè)缺點(diǎn),一是不夠語(yǔ)義化,它的含義是找到參數(shù)值的第一個(gè)出現(xiàn)位置,所以要去比較是否不等于-1,表達(dá)起來(lái)不夠直觀。二是,它內(nèi)部使用嚴(yán)格相等運(yùn)算符(===)進(jìn)行判斷,這會(huì)導(dǎo)致對(duì)NaN的誤判。

ES6 明確將數(shù)組的空位轉(zhuǎn)為undefined。


ES5 比較兩個(gè)值是否相等,只有兩個(gè)運(yùn)算符:相等運(yùn)算符(==)和嚴(yán)格相等運(yùn)算符(===)。它們都有缺點(diǎn),前者會(huì)自動(dòng)轉(zhuǎn)換數(shù)據(jù)類型,后者的NaN不等于自身,以及+0等于-0 用來(lái)解決這個(gè)問(wèn)題。Object.is就是部署這個(gè)算法的新方法。它用來(lái)比較兩個(gè)值是否嚴(yán)格相等,與嚴(yán)格比較運(yùn)算符(===)的行為基本一致。


Object.assign方法用于對(duì)象的合并,將源對(duì)象(source)的所有可枚舉屬性,復(fù)制到目標(biāo)對(duì)象(target)。Object.assign拷貝的屬性是有限制的,只拷貝源對(duì)象的自身屬性(不拷貝繼承屬性),也不拷貝不可枚舉的屬性(enumerable: false)。
注意點(diǎn)(1)淺拷貝(2)同名屬性的替換(3)數(shù)組的處理(4)取值函數(shù)的處理
常見用途(1)為對(duì)象添加屬性(2)為對(duì)象添加方法(3)克隆對(duì)象(4)合并多個(gè)對(duì)象(5)為屬性指定默認(rèn)值


對(duì)象的每個(gè)屬性都有一個(gè)描述對(duì)象(Descriptor),用來(lái)控制該屬性的行為。Object.getOwnPropertyDescriptor方法可以獲取該屬性的描述對(duì)象。描述對(duì)象的enumerable屬性,稱為”可枚舉性“,如果該屬性為false,就表示某些操作會(huì)忽略當(dāng)前屬性。

“可枚舉”(enumerable)這個(gè)概念的最初目的,就是讓某些屬性可以規(guī)避掉for...in操作,不然所有內(nèi)部屬性和方法都會(huì)被遍歷到。比如,對(duì)象原型的toString方法,以及數(shù)組的length屬性,就通過(guò)“可枚舉性”,從而避免被for...in遍歷到。

Object.getOwnPropertyDescriptor(Object.prototype, 'toString').enumerable
// false

從兼容性的角度,都不要使proto
用這個(gè)屬性,而是使用下面的 Object.setPrototypeOf() (寫操作)、 Object.getPrototypeOf() (讀操
作)、 Object.create() (生成操作)代替。


Object.entries 的基本用途是遍歷對(duì)象的屬性,
Object.entries 方法的一個(gè)用處是,將對(duì)象轉(zhuǎn)為真正的 Map 結(jié)構(gòu)。var map = new Map(Object.entries(obj));
擴(kuò)展運(yùn)算符( ... )用于取出參數(shù)對(duì)象的所有可遍歷屬性,拷貝到當(dāng)前對(duì)象之中。等同于使用 Object.assign 方法。

let aClone = { ...a };
// 等同于
let aClone = Object.assign({}, a);

ES6引入了一種新的原始數(shù)據(jù)類型Symbol,表示獨(dú)一無(wú)二的值。它是JavaScript語(yǔ)言的第七種數(shù)據(jù)類型,前六種是:Undefined、
Null、布爾值(Boolean)、字符串(String)、數(shù)值(Number)、對(duì)象(Object)。

Symbol值通過(guò) Symbol

函數(shù)生成。這就是說(shuō),對(duì)象的屬性名現(xiàn)在可以有兩種類型,一種是原來(lái)就有的字符串,另一種就是新增
的Symbol類型。凡是屬性名屬于Symbol類型,就都是獨(dú)一無(wú)二的,可以保證不會(huì)與其他屬性名產(chǎn)生沖突。
在對(duì)象的內(nèi)部,使用Symbol值定義屬性時(shí),Symbol值必須放在方括號(hào)之中。

let s = Symbol();
typeof s
// "symbol"

Symbol值可以顯式轉(zhuǎn)為字符串。也可以轉(zhuǎn)為布爾值,但是不能轉(zhuǎn)為數(shù)值。

Symbol作為屬性名,該屬性不會(huì)出現(xiàn)在 for...in 、 for...of 循環(huán)中,也不會(huì)
被 Object.keys() 、 Object.getOwnPropertyNames() 返回,它也不是私有屬性,有一
個(gè) Object.getOwnPropertySymbols 方法,可以獲取指定對(duì)象的所有Symbol屬性名。這就造成了一種非私有的內(nèi)部方法的效果。

Symbol.for() 與 Symbol() 這兩種寫法,都會(huì)生成新的Symbol。它們的區(qū)別是,前者會(huì)被登記在全局環(huán)境中供搜索,后者
不會(huì)。 Symbol.for() 不會(huì)每次調(diào)用就返回一個(gè)新的Symbol類型的值,而是會(huì)先檢查給定的key是否已經(jīng)存在,如果不存在才
會(huì)新建一個(gè)值。


Proxy可以譯為“代理器”,ES6原生提供Proxy構(gòu)造函數(shù),用來(lái)生成Proxy實(shí)例。

var proxy = new Proxy(target, handler);
Proxy對(duì)象的所有用法,都是上面這種形式,不同的只是 handler 參數(shù)的寫法。其中, new Proxy() 表示生成一個(gè)Proxy實(shí)
例,target參數(shù)表示所要攔截的目標(biāo)對(duì)象, handler 參數(shù)也是一個(gè)對(duì)象,用來(lái)定制攔截行為。
Proxy.revocable方法返回一個(gè)可取消的Proxy實(shí)例


Reflect 對(duì)象與 Proxy 對(duì)象一樣,也是ES6為了操作對(duì)象而提供的新API。
將 Object 對(duì)象的一些明顯屬于語(yǔ)言內(nèi)部的方法(比如 Object.defineProperty ),放到 Reflect 對(duì)象上。


ES6提供了新的數(shù)據(jù)結(jié)構(gòu)Set。它類似于數(shù)組,但是成員的值都是唯一的,沒有重復(fù)的值。通過(guò) add 方法向Set結(jié)構(gòu)加入成員,結(jié)果表明Set結(jié)構(gòu)不會(huì)添加重復(fù)的值,一種去除數(shù)組重復(fù)成員的方法

// 去除數(shù)組的重復(fù)成員
[...new Set(array)] 或 Array.from(new Set(array));

操作:add(value),delete(value),has(value),clear()

遍歷:keys(),values(),entries(),forEach()


WeakSet結(jié)構(gòu)與Set類似,也是不重復(fù)的值的集合。但是,它與Set有兩個(gè)區(qū)別。

首先,WeakSet的成員只能是對(duì)象,而不能是其他類型的值。

其次,WeakSet中的對(duì)象都是弱引用,即垃圾回收機(jī)制不考慮WeakSet對(duì)該對(duì)象的引用,也就是說(shuō),如果其他對(duì)象都不再引用該
對(duì)象,那么垃圾回收機(jī)制會(huì)自動(dòng)回收該對(duì)象所占用的內(nèi)存,不考慮該對(duì)象還存在于WeakSet之中。這個(gè)特點(diǎn)意味著,無(wú)法引用
WeakSet的成員,因此WeakSet是不可遍歷的。


ES6提供了Map數(shù)據(jù)結(jié)構(gòu),Object結(jié)構(gòu)提供了“字符串—值”的對(duì)應(yīng),Map結(jié)構(gòu)提供了“值—值”的對(duì)應(yīng),是一種更
完善的Hash結(jié)構(gòu)實(shí)現(xiàn),Map的鍵實(shí)際上是跟內(nèi)存地址綁定的,只要內(nèi)存地址不一樣,就視為兩個(gè)鍵
Map原生提供三個(gè)遍歷器生成函數(shù)keys(),values(),entries(),forEach()

與其他數(shù)據(jù)結(jié)構(gòu)的互相轉(zhuǎn)換

  • (1)Map轉(zhuǎn)為數(shù)組:就是使用擴(kuò)展運(yùn)算符(...)。
  • (2)數(shù)組轉(zhuǎn)為Map:將數(shù)組轉(zhuǎn)入Map構(gòu)造函數(shù),就可以轉(zhuǎn)為Map。
  • (3)Map轉(zhuǎn)為對(duì)象:Object.create()
  • (4)對(duì)象轉(zhuǎn)為Map:Object.keys(obj) strMap.set(k, obj[k]);
  • (5)Map轉(zhuǎn)為JSON,JSON轉(zhuǎn)MAP

任何數(shù)據(jù)結(jié)構(gòu)只要部署,Iterator接口,就可以完成遍歷操作,引入了 for...of 循環(huán),作為遍歷所有數(shù)據(jù)結(jié)構(gòu)的統(tǒng)一的方法。一個(gè)數(shù)據(jù)結(jié)構(gòu)只要部署
了 Symbol.iterator 屬性,就被視為具有iterator接口,就可以用 for...of 循環(huán)遍歷它的成員。也就是說(shuō), for...of 循環(huán)
內(nèi)部調(diào)用的是數(shù)據(jù)結(jié)構(gòu)的 Symbol.iterator 方法。

與其他遍歷語(yǔ)法的比較:

for循環(huán):寫法比較麻煩;

數(shù)組提供內(nèi)置forEach:無(wú)法中途跳出
forEach 循環(huán),break命令或return命令都不能奏效;

for...in循環(huán)有幾個(gè)缺點(diǎn):
數(shù)組的鍵名是數(shù)字,但是for...in循環(huán)是以字符串作為鍵名“0”、“1”、“2”等等。
for...in循環(huán)不僅遍歷數(shù)字鍵名,還會(huì)遍歷手動(dòng)添加的其他鍵,甚至包括原型鏈上的鍵。
某些情況下,for...in循環(huán)會(huì)以任意順序遍歷鍵名。
總之, for...in 循環(huán)主要是為遍歷對(duì)象而設(shè)計(jì)的,不適用于遍歷數(shù)組


for...of

循環(huán)相比上面幾種做法:
有著同for...in一樣的簡(jiǎn)潔語(yǔ)法,但是沒有for...in那些缺點(diǎn)。
不同用于forEach方法,它可以與break、continue和return配合使用。
提供了遍歷所有數(shù)據(jù)結(jié)構(gòu)的統(tǒng)一操作接口。


Promise 是異步編程的一種解決方案,原生提供了Promise對(duì)象,有三種狀態(tài):pending(進(jìn)行中)、fulfilled(已成功)和rejected(已失?。坏顟B(tài)改變,就不會(huì)再變,任何時(shí)候都可以得到這個(gè)結(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è)階段(剛剛開始還是即將完成)。
resolve函數(shù)的作用是,將Promise對(duì)象的狀態(tài)從“未完成”變?yōu)椤俺晒Α保磸?pending 變?yōu)?resolved)
reject函數(shù)的作用是,將Promise對(duì)象的狀態(tài)從“未完成”變?yōu)椤笆 保磸?pending 變?yōu)?rejected)

then方法返回的是一個(gè)新的Promise實(shí)例(注意,不是原來(lái)那個(gè)Promise實(shí)例)。因此可以采用鏈?zhǔn)綄懛?/p>

Promise 對(duì)象的錯(cuò)誤具有“冒泡”性質(zhì),會(huì)一直向后傳遞,直到被捕獲為止。也就是說(shuō),錯(cuò)誤總是會(huì)被下一個(gè)catch語(yǔ)句捕獲。一般來(lái)說(shuō),不要在then方法里面定義 Reject 狀態(tài)的回調(diào)函數(shù)(即then的第二個(gè)參數(shù)),總是使用catch方法。
const p = Promise.all([p1, p2, p3]);
Promise.all方法接受一個(gè)數(shù)組作為參數(shù),p1、p2、p3都是 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ù)。

Promise.race方法同樣是將多個(gè) Promise 實(shí)例,包裝成一個(gè)新的 Promise 實(shí)例。
const p = Promise.race([p1, p2, p3]);

上面代碼中,只要p1、p2、p3之中有一個(gè)實(shí)例率先改變狀態(tài),p的狀態(tài)就跟著改變。那個(gè)率先改變的 Promise 實(shí)例的返回值,就傳遞給p的回調(diào)函數(shù)。

將現(xiàn)有對(duì)象轉(zhuǎn)為 Promise 對(duì)象,Promise.resolve方法就起到這個(gè)作用
Promise.resolve('foo')
// 等價(jià)于
new Promise(resolve => resolve('foo'))


async 函數(shù)是什么?一句話,它就是 Generator 函數(shù)的語(yǔ)法糖。async函數(shù)就是將 Generator 函數(shù)的星號(hào)(*)替換成async,將yield替換成await,僅此而已。
async函數(shù)對(duì) Generator 函數(shù)的改進(jìn),體現(xiàn)在以下四點(diǎn):
(1)內(nèi)置執(zhí)行器。(2)更好的語(yǔ)義。(3)更廣的適用性。(4)返回值是 Promise。
只有async函數(shù)內(nèi)部的異步操作執(zhí)行完,才會(huì)執(zhí)行外面的then方法指定的回調(diào)函數(shù)

// 函數(shù)聲明
async function foo() {}
// 函數(shù)表達(dá)式
const foo = async function () {};
// 箭頭函數(shù)
const foo = async () => {};

如果希望多個(gè)請(qǐng)求并發(fā)執(zhí)行,可以使用Promise.all方法。
async 函數(shù)的實(shí)現(xiàn)原理,就是將 Generator 函數(shù)和自動(dòng)執(zhí)行器,包裝在一個(gè)函數(shù)里。

next方法必須是同步的,只要調(diào)用就必須立刻返回值。也就是說(shuō),一旦執(zhí)行next方法,就必須同步地得到value和done這兩個(gè)屬性。如果遍歷指針正好指向同步操作,當(dāng)然沒有問(wèn)題,但對(duì)于異步操作,就不太合適了。目前的解決方法是,Generator 函數(shù)里面的異步操作,返回一個(gè) Thunk 函數(shù)或者 Promise 對(duì)象,即value屬性是一個(gè) Thunk 函數(shù)或者 Promise 對(duì)象,等待以后返回真正的值,而done屬性則還是同步產(chǎn)生的


for...of循環(huán)用于遍歷同步的 Iterator 接口。新引入的for await...of循環(huán),則是用于遍歷異步的 Iterator 接口。
異步 Generator 函數(shù)出現(xiàn)以后,JavaScript 就有了四種函數(shù)形式:普通函數(shù)、async 函數(shù)、Generator 函數(shù)和異步 Generator 函數(shù)


Generator函數(shù)是ES6提供的一種異步編程解決方案,語(yǔ)法行為與傳統(tǒng)函數(shù)完全不同,形式上,Generator函數(shù)是一個(gè)普通函數(shù),但是有兩個(gè)特征。一是, function 關(guān)鍵字與函數(shù)名之間有一個(gè)星號(hào);二是,函數(shù)體
內(nèi)部使用 yield 語(yǔ)句,定義不同的內(nèi)部狀態(tài).
Generator函數(shù)的調(diào)用方法與普通函數(shù)一樣,也是在函數(shù)名后面加上一對(duì)圓括號(hào)。不同的是,調(diào)用Generator函數(shù)后并不執(zhí)行,返回的也不是函數(shù)運(yùn)行結(jié)果,而是一個(gè)指向內(nèi)部狀態(tài)的指針對(duì)象,必須調(diào)用遍歷器對(duì)象的next方法,使得指針移向下一個(gè)狀態(tài)。也就是說(shuō),每次調(diào)用 next 方法,內(nèi)部指針就從函數(shù)頭部或上一次停下來(lái)的地方開始執(zhí)行,直到遇到下一個(gè) yield 語(yǔ)句(或 return 語(yǔ)句)為止。

Generator函數(shù)是分段執(zhí)行的, yield 語(yǔ)句是暫停執(zhí)行的標(biāo)記,而 next 方法可以恢復(fù)執(zhí)行。

next方法返回值的value屬性,是Generator函數(shù)向外輸出數(shù)據(jù);next方法還可以接受參數(shù),這是向Generator函數(shù)體內(nèi)輸入數(shù)據(jù),傳入
Generator 函數(shù),作為上個(gè)階段異步任務(wù)的返回結(jié)果

Generator函數(shù)可以返回一系列的值,因?yàn)榭梢杂腥我舛鄠€(gè) yield,yield后面的表達(dá)式 123 + 456 ,不會(huì)立即求值,只會(huì)在 next 方法將指針移到這一句時(shí),才會(huì)求值,Generator函數(shù)可以不用 yield 語(yǔ)句,這時(shí)就變成了一個(gè)單純的暫緩執(zhí)行函數(shù)。

yield 句本身沒有返回值,或者說(shuō)總是返回 undefined 。 next 方法可以帶一個(gè)參數(shù),該參數(shù)就會(huì)被當(dāng)作上一
個(gè) yield 語(yǔ)句的返回值。

for...of 循環(huán)可以自動(dòng)遍歷Generator函數(shù),且此時(shí)不再需要調(diào)用 next 方法。

yield* 語(yǔ)句,用來(lái)在一個(gè)Generator函數(shù)里面執(zhí)行另一個(gè)Generator函數(shù)。yield* 不過(guò)是 for...of 的一種簡(jiǎn)寫形式,yield 命令后面如果不加星號(hào),返回的是整個(gè)數(shù)組,加了星號(hào)就表示返回的是數(shù)組的遍歷器對(duì)象。


Generator函數(shù)不能用NEW(會(huì)報(bào)錯(cuò)),又想在函數(shù)里面用THIS ?
首先,生成一個(gè)空對(duì)象,使用 bind 方法綁定Generator函數(shù)內(nèi)部的 this 。這樣,構(gòu)造函數(shù)調(diào)用以
后,這個(gè)空對(duì)象就是Generator函數(shù)的實(shí)例對(duì)象了。

Generator函數(shù)的一個(gè)重要實(shí)際意義就是用來(lái)處理異步操作,改寫回調(diào)函數(shù)


async函數(shù)并不屬于ES6,而是被列入了ES7,但是traceur、Babel.js、regenerator等轉(zhuǎn)碼器已經(jīng)支持這個(gè)功能,轉(zhuǎn)碼后立刻就
能使用。異步編程對(duì)JavaScript語(yǔ)言太重要。Javascript語(yǔ)言的執(zhí)行環(huán)境是“單線程”的,如果沒有異步編程,根本沒法用,非卡死不可。
ES6誕生以前,異步編程的方法,大概有下面四種。
回調(diào)函數(shù)
事件監(jiān)聽
發(fā)布/訂閱
Promise 對(duì)象


類的數(shù)據(jù)類型就是函數(shù),類本身就指向構(gòu)造函數(shù)。

class Point{
// ...
}

typeof Point // "function"
constructor 方法是類的默認(rèn)方法,通過(guò) new 命令生成對(duì)象實(shí)例時(shí),自動(dòng)調(diào)用該方法。一個(gè)類必須有 constructor 方法,
如果沒有顯式定義,一個(gè)空的 constructor 方法會(huì)被默認(rèn)添加。

實(shí)例的屬性除非顯式定義在其本身(即定義在 this 對(duì)象上),否則都是定義在原型上(即定義
在 class 上)。hasOwnProperty方法判斷是本身屬性還是原型屬性。
Class不存在變量提升(hoist),這一點(diǎn)與ES5完全不同。 Class之間可以通過(guò)extends關(guān)鍵字實(shí)現(xiàn)繼承,這比ES5的通過(guò)修改原型鏈實(shí)現(xiàn)繼承,要清晰和方便很多
子類必須在 constructor 方法中調(diào)用 super 方法,否則新建實(shí)例時(shí)會(huì)報(bào)錯(cuò)。這是因?yàn)樽宇悰]有自己的 this 對(duì)象,而是繼
承父類的 this 對(duì)象,然后對(duì)其進(jìn)行加工。如果不調(diào)用 super 方法,子類就得不到 this 對(duì)象。只有調(diào)用 super 之后,才可以使用 this 關(guān)鍵字
類的繼承是按照下面的模式實(shí)現(xiàn)的:Object.setPrototypeOf(B.prototype, A.prototype);
Object.getPrototypeOf 方法可以用來(lái)從子類上獲取父類。因此,可以使用這個(gè)方法判斷,一個(gè)類是否繼承了另一個(gè)類。

如果在一個(gè)方法前,加上 static 關(guān)鍵字,就表示該方法不會(huì)被實(shí)例繼承,而是直接通過(guò)類來(lái)調(diào)用,這就稱為“靜態(tài)方法”。
父類的靜態(tài)方法,可以被子類繼承

靜態(tài)屬性指的是Class本身的屬性,即 Class.propname ,而不是定義在實(shí)例對(duì)象( this )上的屬性。


修飾器(Decorator)是一個(gè)函數(shù),用來(lái)修改類的行為。這是ES7的一個(gè)提案,目前Babel轉(zhuǎn)碼器已經(jīng)支持。類似和類,方法,屬性添加JAVA注解的功能


在ES6之前,社區(qū)制定了一些模塊加載方案,最主要的有CommonJS和AMD兩種。前者用于服務(wù)器,后者用于瀏覽器,ES6模塊的設(shè)計(jì)思想,是盡量的靜態(tài)化,使得編譯時(shí)就能確定模塊的依賴關(guān)系,以及輸入和輸出的變量。CommonJS和AMD模塊,都只能在運(yùn)行時(shí)確定這些東西。
let { stat, exists, readFile } = require('fs') 這種加載稱為“運(yùn)行時(shí)加載”
import { stat, exists, readFile } from 'fs' 這種加載稱為“編譯時(shí)加載”
ES6的模塊自動(dòng)采用嚴(yán)格模式

模塊功能主要由兩個(gè)命令構(gòu)成: export 和 import,export 命令用于規(guī)定模塊的對(duì)外接口, import 命令用于輸入其他
模塊提供的功能,export 和 import 命令如果處于塊級(jí)作用域內(nèi),就會(huì)報(bào)錯(cuò)。因?yàn)樘幱跅l件代碼塊之中,就沒法做靜態(tài)優(yōu)化了,違背了ES6模塊的設(shè)計(jì)初衷

模塊的整體加載 import * as circle from './circle';
export default 命令,為模塊指定默認(rèn)輸出,一個(gè)模塊只能有一個(gè)默認(rèn)輸出,所以, import 命令后面才不用加大括號(hào),因?yàn)橹豢赡軐?duì)應(yīng)一個(gè)方法

ES6模塊是動(dòng)態(tài)引用,并且不會(huì)緩存值,模塊里面的變量綁定其所在的模塊


編碼規(guī)范:

(1)let取代var

(2)全局常量和線程安全:在 let 和 const 之間,建議優(yōu)先使用 const ,尤其是在全局環(huán)境,不應(yīng)該設(shè)置變量,只應(yīng)設(shè)置常量。

..靜態(tài)字符串一律使用單引號(hào)或反引號(hào),不使用雙引號(hào)。動(dòng)態(tài)字符串使用反引號(hào)。

..使用數(shù)組成員對(duì)變量賦值時(shí)、函數(shù)返回多個(gè)值,優(yōu)先使用解構(gòu)賦值。

..單行定義的對(duì)象,最后一個(gè)成員不以逗號(hào)結(jié)尾。多行定義的對(duì)象,最后一個(gè)成員以逗號(hào)結(jié)尾。

..對(duì)象盡量靜態(tài)化,一旦定義,就不得隨意添加新的屬性。如果添加屬性不可避免,要使用 Object.assign 方法
..使用擴(kuò)展運(yùn)算符(...)拷貝數(shù)組,使用Array.from方法,將類似數(shù)組的對(duì)象轉(zhuǎn)為數(shù)組。

..立即執(zhí)行函數(shù)可以寫成箭頭函數(shù)的形式,那些需要使用函數(shù)表達(dá)式的場(chǎng)合,盡量用箭頭函數(shù)代替。因?yàn)檫@樣更簡(jiǎn)潔,而且綁定了this。

..不要在函數(shù)體內(nèi)使用arguments變量,使用rest運(yùn)算符(...)代替

..總是用Class,取代需要prototype的操作
..Module語(yǔ)法是JavaScript模塊的標(biāo)準(zhǔn)寫法,堅(jiān)持使用這種寫法。使用 import 取代 require 。


?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 229,001評(píng)論 6 537
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 98,786評(píng)論 3 423
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人,你說(shuō)我怎么就攤上這事?!?“怎么了?”我有些...
    開封第一講書人閱讀 176,986評(píng)論 0 381
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我,道長(zhǎng),這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 63,204評(píng)論 1 315
  • 正文 為了忘掉前任,我火速辦了婚禮,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 71,964評(píng)論 6 410
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 55,354評(píng)論 1 324
  • 那天,我揣著相機(jī)與錄音,去河邊找鬼。 笑死,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,410評(píng)論 3 444
  • 文/蒼蘭香墨 我猛地睜開眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 42,554評(píng)論 0 289
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 49,106評(píng)論 1 335
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 40,918評(píng)論 3 356
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 43,093評(píng)論 1 371
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,648評(píng)論 5 362
  • 正文 年R本政府宣布,位于F島的核電站,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 44,342評(píng)論 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,755評(píng)論 0 28
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 36,009評(píng)論 1 289
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 51,839評(píng)論 3 395
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 48,107評(píng)論 2 375

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

  • title: promise總結(jié) 總結(jié)在前 前言 下文類似 Promise#then、Promise#resolv...
    JyLie閱讀 12,278評(píng)論 1 21
  • 本文為阮一峰大神的《ECMAScript 6 入門》的個(gè)人版提純! babel babel負(fù)責(zé)將JS高級(jí)語(yǔ)法轉(zhuǎn)義,...
    Devildi已被占用閱讀 2,011評(píng)論 0 4
  • 異步編程對(duì)JavaScript語(yǔ)言太重要。Javascript語(yǔ)言的執(zhí)行環(huán)境是“單線程”的,如果沒有異步編程,根本...
    呼呼哥閱讀 7,323評(píng)論 5 22
  • [TOC] 參考阮一峰的ECMAScript 6 入門參考深入淺出ES6 let和const let和const都...
    郭子web閱讀 1,803評(píng)論 0 1
  • 姐妹相聚,總是有說(shuō)不完的話,在一起吃吃飯,聊聊天,每個(gè)瞬間都那么美好。1993——2018時(shí)光匆匆,姐妹情濃。[愛...
    有鳳來(lái)儀的簡(jiǎn)書閱讀 263評(píng)論 2 2