ECMAScript是JavaScript所基於的標準,通常被簡稱為ES。了解有關ECMAScript的所有信息,以及ES2018(也稱為ES9)中新增的功能。

ES2018是ECMAScript標準的最新版本。

它引入了哪些新功能?

Rest/Spread 屬性

ES6在處理數組解構時引入了“rest”元素的概念:

const numbers = [1, 2, 3, 4, 5]
[first, second, ...others] = numbers

以及spread元素

const numbers = [1, 2, 3, 4, 5]
const sum = (a, b, c, d, e) => a + b + c + d + e
const sumOfNumbers = sum(...numbers)

ES2018引入了同樣功能,但針對對象。

Rest 屬性

const { first, second, ...others } = { first: 1, second: 2, third: 3, fourth: 4, fifth: 5 }

first // 1
second // 2
others // { third: 3, fourth: 4, fifth: 5 }

Spread 屬性允許通過結合在spread運算符之後傳遞的對象的屬性來創建新對象:

const items = { first, second, ...others }
items //{ first: 1, second: 2, third: 3, fourth: 4, fifth: 5 }

異步迭代

新的for-await-of構造允許將異步可迭代對象用作循環迭代:

for await (const line of readLines(filePath)) {
 console.log(line)
}

由於它使用了await,因此只能在async函數內部使用它,就像普通的await一樣(請參閱async/await)。

Promise.prototype.finally()

當一個Promise成功完成時,它依次調用then()方法。

如果此過程中出現錯誤,則跳過then()方法並執行catch()方法。

finally()允許您無論Promise成功執行與否都運行一些代碼:

fetch('file.json')
 .then(data => data.json())
 .catch(error => console.error(error))
 .finally(() => console.log('finished'))

正則表達式改進

RegExp 正向匹配斷言:基於前置字符進行匹配

這是一個向前看的操作:使用?=來匹配後跟特定子串的字符串:

/Roger(?=Waters)/

/Roger(?= Waters)/.test('Roger is my dog') //false
/Roger(?= Waters)/.test('Roger is my dog and Roger Waters is a famous musician') //true

?!執行相反的操作,匹配字符串是否不是後跟特定子串:

/Roger(?!Waters)/

/Roger(?! Waters)/.test('Roger is my dog') //true
/Roger(?! Waters)/.test('Roger Waters is a famous musician') //false

向前看使用?=符號。它們已經存在。

新功能:向後查找使用?<=

/(?<=Roger) Waters/

/(?<=Roger) Waters/.test('Pink Waters is my dog') //false
/(?<=Roger) Waters/.test('Roger is my dog and Roger Waters is a famous musician') //true

使用?<!來否定向後查找:

/(?<!Roger) Waters/

/(?<!Roger) Waters/.test('Pink Waters is my dog') //true
/(?<!Roger) Waters/.test('Roger is my dog and Roger Waters is a famous musician') //false

Unicode 屬性逸脫\p{…}\P{…}

在正則表達式模式中,您可以使用\d來匹配任何數字,\s來匹配除空白字符外的任何字符,\w來匹配任何字母數字字符等。

這個新功能將此概念擴展到所有Unicode字符,引入了\p{}及其否定\P{}

任何Unicode字符都有一組屬性。例如,Script用於確定語言系列,ASCII是一個布爾值,對於ASCII字符為真,等等。您可以將此屬性置於括號中,在正則表達式中檢查其為真假:

/^\p{ASCII}+$/u.test('abc') //✅
/^\p{ASCII}+$/u.test('ABC@') //✅
/^\p{ASCII}+$/u.test('ABC🙃') //❌

ASCII_Hex_Digit是另一個布爾屬性,用於檢查字符串是否只包含有效的十六進制數字:

/^\p{ASCII\_Hex\_Digit}+$/u.test('0123456789ABCDEF') //✅
/^\p{ASCII\_Hex\_Digit}+$/u.test('h') //❌

還有許多其他布爾屬性,您只需將其名稱添加到括號中即可檢查,包括UppercaseLowercaseWhite_SpaceAlphabeticEmoji等等:

/^\p{Lowercase}$/u.test('h') //✅
/^\p{Uppercase}$/u.test('H') //✅

/^\p{Emoji}+$/u.test('H') //❌
/^\p{Emoji}+$/u.test('🙃🙃') //✅

除了這些二進制屬性外,您還可以檢查任何Unicode字符屬性以匹配特定值。在此示例中,我檢查字符串是否使用希臘字母或拉丁字母書寫:

/^\p{Script=Greek}+$/u.test('ελληνικά') //✅
/^\p{Script=Latin}+$/u.test('hey') //✅

您可以在此提案上直接閱讀到有關所有可用屬性的更多信息

命名捕獲組

在ES2018中,可以將捕獲組分配給一個名稱,而不只是將其分配給預定義的槽位:

const re = /(?<year>\d{4})-(?<month>\d{2})-(?<day>\d{2})/
const result = re.exec('2015-01-02')

// result.groups.year === '2015';
// result.groups.month === '01';
// result.groups.day === '02';

正則表達式的s標記

s標記,簡稱單行模式,使.匹配換行字符。如果沒有s標記,點將匹配真正字符,而不是換行:

/hi.welcome/.test('hi\nwelcome') // false
/hi.welcome/s.test('hi\nwelcome') // true