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