es7新特性
Es7在ES6的基礎上添加了三項內容:javascript
*求冪運算符 (**)
Array.prototype.includes()方法.
函數做用域中嚴格模式的變動css
Array.prototype.includes( )html
includes()的做用,是查找一個值在不在數組裏,若在,則返回true,反之返回falsejava
Array.prototype.includes()方法接收兩個參數:要搜索的值和搜索的開始索引。當第二個參數被傳入時,該方法會從索引處開始日後es6
搜索(默認索引值爲0)。若搜索值在數組中存在則返回true,不然返回false。web
includes()方法有一點不一樣,兩個NaN被認爲是相等的,即便在NaN === NaN結果是false的狀況下。
這一點和indexOf()的行爲不一樣,indexOf()嚴格使用===判斷
includes()還有一個怪異的點須要指出,在判斷 +0 與 -0 時,被認爲是相同的。
在這一點上indexOf()與includes()的處理結果是同樣的,前者一樣會返回 +0 的索引值正則表達式
es8新特性
異步函數(async function)
因爲javascript是單線程的
作法一般是經過回調函數實現JavaScript的異步編程
假如存在還有更多的請求操做就會出現多層嵌套代碼就會亂成一團 這種狀況就被稱之爲回調函數地獄
因而promise被提出了它將回調函數的嵌套改爲了鏈式調用express
promise的最大問題是代碼冗餘 ,請求任務時一堆的then,也使原來的語義變得很不清楚此時咱們能夠引入另一種異步編程的機制:generator編程
Es8引入了async函數使得異步操做變得更加方便
實例以下:segmentfault
Async function asyncFunc(params){ const result1 = await this.login() const result2 = await this.getInfo() }
異步函數存在如下四種使用形式:
函數聲明: async function foo() {}
函數表達式: const foo = async function() {}
對象的方式: let obj = { async foo() {} }
箭頭函數: const foo = async () => {}
處理單個異步結果:
async function asyncFunc(){ const result = await otherAsyncFunc(); console.log(result) }
順序處理多個異步結果:
async function asyncFunc(){ const result1 = await otherAsyncFunc1(); console.log(result1); const result2 = await otherAsyncFunc2(); console.log(result2); }
並行處理多個異步結果:
async function asyncFunc(){ const [result1,result2] = await.Promise.all({ otherAsyncFunc1(), otherAsyncFunc2() }) console.log(result1,result2); }
處理錯誤:
Async function asyncFunc(){ try{ Await otherAsyncFunc(); }catch(err){ console.log(err) } }
Object.entries( )和Object.values( )
Object.entries( )
1.目標對象是對象時,則每個鍵值對都將會編譯成一個具備兩個元素的數組
2.目標對象是數組時,則會將數組的下標做爲鍵值返回
Object.entries({ one:1,two:2}) //[[‘one’,1],[’two’,2]] Object.entries([1,2]) //[[‘0’,1],[‘1’,2]]
注意:鍵值對中,若是鍵的值是Symbol,編譯時將會被忽略。例如:
Object.entries({ [Symbol()]: 1, two: 2 }) //[['two', 2]]
Object.entries()返回的數組的順序與for-in循環保持一致,即若是對象的key值是數字,則返回值會對key值進行排序,返回的是排序後的結果。例如:
Object.entries({ 3: 'a', 4: 'b', 1: 'c' }) //[['1', 'c'], ['3', 'a'], ['4', 'b']]
使用Object.entries(),咱們還能夠進行對象屬性的遍歷。例如
let obj = { one: 1, two: 2 }; for (let [k,v] of Object.entries(obj)) { console.log(`${JSON.stringify(k)}: ${JSON.stringify(v)}`); }
//輸出結果以下:
'one': 1
'two': 2
Object.values()
它的工做原理跟Object.entries()很像,顧名思義,它只返回本身的鍵值對中屬性的值。它返回的數組順序,也跟Object.entries()保持一致。
Object.values({ one: 1, two: 2 }) //[1, 2]
Object.values({ 3: 'a', 4: 'b', 1: 'c' }) //['c', 'a', 'b']
字符串填充:padStart和padEnd
ES8提供了新的字符串方法-padStart和padEnd。padStart函數經過填充字符串的首部來保證字符串達到固定的長度,反之,padEnd是填充字符串的尾部來保證字符串的長度的。該方法提供了兩個參數:字符串目標長度和填充字段,其中第二個參數能夠不填,默認狀況下使用空格填充。
'Vue'.padStart(10) //' Vue' 'React'.padStart(10) //' React' 'JavaScript'.padStart(10) //'JavaScript'
能夠看出,多個數據若是都採用一樣長度的padStart,至關於將呈現內容右對齊。
上面示例中咱們只定義了第一個參數,那麼咱們如今來看看第二個參數,咱們能夠指定字符串來代替空字符串。
'Vue'.padStart(10, '_*') //'_*_*_*_Vue' 'React'.padStart(10, 'Hello') //'HelloReact' 'JavaScript'.padStart(10, 'Hi') //'JavaScript' 'JavaScript'.padStart(8, 'Hi') //'JavaScript'
從上面結果來看,填充函數只有在字符長度小於目標長度時纔有效,若字符長度已經等於或小於目標長度時,填充字符不會起做用,並且目標長度若是小於字符串自己長度時,字符串也不會作截斷處理,只會原樣輸出。
padEnd函數做用同padStart,只不過它是從字符串尾部作填充。來看個小例子:
'Vue'.padEnd(10, '_*') //'Vue_*_*_*_' 'React'.padEnd(10, 'Hello') //'ReactHello' 'JavaScript'.padEnd(10, 'Hi') //'JavaScript' 'JavaScript'.padEnd(8, 'Hi') //'JavaScript'
Object.getOwnPropertyDescriptors()
顧名思義,該方法會返回目標對象中全部屬性的屬性描述符,該屬性必須是對象本身定義的,不能是從原型鏈繼承來的。先來看個它的基本用法:
let obj = { id: 1, name: 'test', get gender() { console.log('gender') }, set grade(g) { console.log(g) } } Object.getOwnPropertyDescriptors(obj)
//輸出結果爲:
{ gender: { configurable: true, enumerable: true, get: f gender(), set: undefined }, grade: { configurable: true, enumerable: true, get: undefined, set: f grade(g) }, id: { configurable: true, enumerable: true, value: 1, writable: true }, name: { configurable: true, enumerable: true, value: 'test', writable: true } }
方法還提供了第二個參數,用來獲取指定屬性的屬性描述符。
let obj = { id: 1, name: 'test', get gender() { console.log('gender') }, set grade(g) { console.log(g) } } Object.getOwnPropertyDescriptors(obj, 'id')
//輸出結果爲:
{ id: { configurable: true, enumerable: true, value: 1, writable: true } }
由上述例子可知,該方法返回的描述符,會有兩種類型:數據描述符、存取器描述符。返回結果中包含的鍵可能的值有:configurable、enumerable、value、writable、get、set。
使用過Object.assign()的同窗都知道,assign方法只能拷貝一個屬性的值,而不會拷貝它背後的複製方法和取值方法。Object.getOwnPropertyDescriptors()主要是爲了解決Object.assign()沒法正確拷貝get屬性和set屬性的問題。
let obj = { id: 1, name: 'test', get gender() { console.log('gender') } } Object.assign(obj)
//輸出結果爲:
{ gender: undefined id: 1, name: 'test' }
此時,Object.getOwnPropertyDescriptors方法配合Object.defineProperties方法,就能夠實現正確拷貝。
let obj = { id: 1, name: 'test', get gender() { console.log('gender') } } let obj1 = {} Object.defineProperties(obj1, Object.getOwnPropertyDescriptors(obj)) Object.getOwnPropertyDescriptors(obj1)
//輸出結果爲:
{ gender: { configurable: true, enumerable: true, get: f gender(), set: undefined }, id: { configurable: true, enumerable: true, value: 1, writable: true }, name: { configurable: true, enumerable: true, value: 'test', writable: true } }
上述代碼演示了,咱們如何來拷貝一個屬性值爲賦值方法或者取值方法的對象。更多Object.getOwnPropertyDescriptors的使用細則,可參見阮一峯的博客文章,連接奉上:http://es6.ruanyifeng.com/#docs/object#Object-getOwnPropertyDescriptors
共享內存和原子(Shared memory and atomics)
ES8引入了兩部份內容:新的構造函數SharedArrayBuffer、具備輔助函數的命名空間對象Atomics。共享內存容許多個線程併發讀寫數據,而原子操做則可以進行併發控制,確保多個存在競爭關係的線程順序執行。
共享內存和原子也稱爲共享陣列緩衝區,它是更高級的併發抽象的基本構建塊。它容許在多個工做者和主線程之間共享SharedArrayBuffer對象的字節(緩衝區是共享的,用以訪問字節,將其包裝在類型化的數組中)。這種共享有兩個好處:
能夠更快地在web worker之間共享數據
web worker之間的協調變得更加簡單和快速
那麼,咱們爲何要引入共享內存和原子的概念呢?以及SharedArrayBuffer的競爭條件是什麼,Atomics又是如何解決這種競爭的?推薦下面的文章,文章講解很詳細,圖文並茂,帶你深刻了解SharedArrayBuffer和Atomics。
內存管理碰撞課程:http://www.javashuo.com/article/p-dhecnndn-gq.html
圖解 ArrayBuffers 和 SharedArrayBuffers:http://www.javashuo.com/article/p-zikhikoa-ev.html
用 Atomics 避免 SharedArrayBuffers 競爭條件:http://www.javashuo.com/article/p-hxxgkqgp-dg.html
Atomics對象提供了許多靜態方法,配合SharedArrayBuffer對象一塊兒使用,能夠幫助咱們去構建一個內存共享的多線程編程環境。Atomic操做安裝在Atomics模塊上。與其餘全局對象不一樣,Atomics不是構造函數。您不能使用new操做符或Atomics做爲函數調用該對象。全部的屬性和方法Atomics都是靜態的,這一點跟Math相似。下面連接貼出了Atomics提供的一些基本方法:
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Atomics
關於共享內存和原子的深刻研究,也能夠參考Axel Rauschmayer博士的《Exploring ES2016 and ES2017》一書中的內容。具體章節連接以下:
http://exploringjs.com/es2016-es2017/ch_shared-array-buffer.html
函數參數列表與調用中的尾部逗號
該特性容許咱們在定義或者調用函數時添加尾部逗號而不報錯。
let foo = function ( a, b, c, ) { console.log('a:', a) console.log('b:', b) console.log('c:', c) } foo(1, 3, 4, )
//輸出結果爲:
a: 1
b: 3
c: 4
上面這種方式調用是沒有問題的。函數的這種尾逗號也是向數組和字面量對象中尾逗號看齊,它適用於那種多行參數而且參數名很長的狀況,開發過程當中,若是忘記刪除尾部逗號也不要緊,ES8已經支持這種寫法。
這麼用有什麼好處呢?
首先,當咱們調整結構時,不會由於最後一行代碼的位置變更,而去添加或者刪除逗號。
其次,在版本管理上,不會出現由於一個逗號,而使原本只有一行的修改,變成兩行。例以下面:
從
(
'abc'
)
到
(
'abc',
'def'
)
在咱們版本管理系統裏,它會監測到你有兩處更改,可是若是咱們沒必要去關心逗號的存在,每一行都有逗號時,新加一行,也只會監測到一行的修改。
建議的ES9功能
回想一下,每一個ECMAScript功能提案都通過了幾個階段:
階段4意味着功能將在下一個版本中(或以後的版本)。
階段3意味着功能仍然有機會被包含在下一個版本中。
第4階段和部分ECMAScript規範草案
如下功能目前在第4階段:
Template Literal Revision:模板文字修訂(蒂姆·迪士尼)
候選功能(第3階段)
如下功能目前在第3階段:
Function.prototype.toString 修訂版(Michael Ficarra)
global(Jordan Harband)
Rest/Spread Properties:Rest/Spread屬性(SebastianMarkbåge)
Asynchronous Iteration:異步迭代(Domenic Denicola)
import() (Domenic Denicola)
RegExp Lookbehind Assertions:RegExp Lookbehind斷言(Daniel Ehrenberg)
RegExp Unicode Property Escapes:RegExp Unicode屬性轉義(Brian Terlson,Daniel Ehrenberg,Mathias Bynens)
RegExp named capture groups:RegExp命名捕獲組(Daniel Ehrenberg,Brian Terlson)
s (dotAll) flag for regular expressions:s(dotAll)標誌爲正則表達式(Mathias Bynens,Brian Terlson)
Promise.prototype.finally() (Jordan Harband)
BigInt - 任意精度整數(Daniel Ehrenberg)
Class fields(Daniel Ehrenberg,Jeff Morrison)
Optional catch binding(Michael Ficarra)
ES6-ES8的學習網站
ES6:http://es6.ruanyifeng.com/
ES7:https://www.css88.com/archives/tag/es7
ES8:https://www.css88.com/archives/tag/es8 TC39提案--javascript發展委員會