本篇文章主要介紹了ES10 特性的完整指南,分享給大家,具體如下:
公司主營業(yè)務(wù):網(wǎng)站設(shè)計制作、成都網(wǎng)站制作、移動網(wǎng)站開發(fā)等業(yè)務(wù)。幫助企業(yè)客戶真正實(shí)現(xiàn)互聯(lián)網(wǎng)宣傳,提高企業(yè)的競爭能力。成都創(chuàng)新互聯(lián)是一支青春激揚(yáng)、勤奮敬業(yè)、活力青春激揚(yáng)、勤奮敬業(yè)、活力澎湃、和諧高效的團(tuán)隊(duì)。公司秉承以“開放、自由、嚴(yán)謹(jǐn)、自律”為核心的企業(yè)文化,感謝他們對我們的高要求,感謝他們從不同領(lǐng)域給我們帶來的挑戰(zhàn),讓我們激情的團(tuán)隊(duì)有機(jī)會用頭腦與智慧不斷的給客戶帶來驚喜。成都創(chuàng)新互聯(lián)推出分宜免費(fèi)做網(wǎng)站回饋大家。
ES10 還只是一個草案。但是除了 Object.fromEntries
之外,Chrome 的大多數(shù)功能都已經(jīng)實(shí)現(xiàn)了,為什么不早點(diǎn)開始探索呢?當(dāng)所有瀏覽器都開始支持它時,你將走在前面,這只是時間問題。
在新的語言特性方面,ES10 不如 ES6 重要,但它確實(shí)添加了一些有趣的特性(其中一些功能目前還無法在瀏覽器中工作: 2019/02/21)
在 ES6 中,箭頭函數(shù)無疑是最受歡迎的新特性,在 ES10 中會是什么呢?
BigInt -任意精度整數(shù)
BigInt 是第七種 原始類型。
BigInt 是一個任意精度的整數(shù)。這意味著變量現(xiàn)在可以 表示²⁵³
數(shù)字,而不僅僅是9007199254740992
。
const b = 1n; // 追加 n 以創(chuàng)建 BigInt
在過去,不支持大于 9007199254740992
的整數(shù)值。如果超過,該值將鎖定為 MAX_SAFE_INTEGER + 1
:
const limit = Number.MAX_SAFE_INTEGER; ⇨ 9007199254740991 limit + 1; ⇨ 9007199254740992 limit + 2; ⇨ 9007199254740992 <--- MAX_SAFE_INTEGER + 1 exceeded const larger = 9007199254740991n; ⇨ 9007199254740991n const integer = BigInt(9007199254740991); // initialize with number ⇨ 9007199254740991n const same = BigInt("9007199254740991"); // initialize with "string" ⇨ 9007199254740991n
typeof
typeof 10; ⇨ 'number' typeof 10n; ⇨ 'bigint'
等于運(yùn)算符可用于兩種類型之間比較:
10n === BigInt(10); ⇨ true 10n == 10; ⇨ true
數(shù)學(xué)運(yùn)算符只能在自己的類型中工作:
200n / 10n ⇨ 20n 200n / 20 ⇨ Uncaught TypeError: Cannot mix BigInt and other types, use explicit conversions <
-運(yùn)算符可以操作, + 不可用
-100n ⇨ -100n +100n ⇨ Uncaught TypeError: Cannot convert a BigInt value to a number
當(dāng)你讀到這篇文章的時候,matchAll 可能已經(jīng)在 Chrome C73 中正式實(shí)現(xiàn)了——如果不是,它仍然值得一看。特別是如果你是一個正則表達(dá)式(regex)愛好者。
string.prototype.matchAll()
如果您運(yùn)行谷歌搜索JavaScript string match all,第一個結(jié)果將是這樣的:如何編寫正則表達(dá)式“match all”?
最佳結(jié)果將建議 String.match 與正則表達(dá)式和 /g 一起使用或者帶有 /g 的 RegExp.exec 或者帶有 /g 的 RegExp.test 。
首先,讓我們看看舊規(guī)范是如何工作的。
帶字符串參數(shù)的 String.match 僅返回第一個匹配:
let string = 'Hello'; let matches = string.match('l'); console.log(matches[0]); // "l"
結(jié)果是單個 "l"
(注意:匹配存儲在 matches[0] 中而不是 matches)
在“hello”
中搜索 "l"
只返回 "l"
。
將 string.match 與 regex 參數(shù)一起使用也是如此:
讓我們使用正則表達(dá)式 /l/
找到字符 串“hello” 中的 “l(fā)”
字符:
let string = "Hello"; let matches = string.match(/l/); console.log(matches[0]); // "l"
添加 /g 混合
let string = "Hello"; let ret = string.match(/l/g); // (2) [“l(fā)”, “l(fā)”];
很好,我們使用 < ES10 方式得到了多個匹配,它一直起作用。
那么為什么要使用全新的 matchAll 方法呢? 在我們更詳細(xì)地回答這個問題之前,讓我們先來看看 捕獲組。如果不出意外,你可能會學(xué)到一些關(guān)于正則表達(dá)式的新知識。
正則表達(dá)式捕獲組
在 regex 中捕獲組只是從 () 括號中提取一個模式,可以使用 /regex/.exec(string) 和string.match 捕捉組。
常規(guī)捕獲組是通過將模式包裝在 (pattern) 中創(chuàng)建的,但是要在結(jié)果對象上創(chuàng)建 groups
屬性,它是: (?
。
要創(chuàng)建一個新的組名,只需在括號內(nèi)附加 ?
字符串標(biāo)本匹配:
這里創(chuàng)建了 match.groups.color 和 match.groups.bird :
const string = 'black*raven lime*parrot white*seagull'; const regex = /(?.*?)\*(? [a-z0-9]+)/g; while (match = regex.exec(string)) { let value = match[0]; let index = match.index; let input = match.input; console.log(`${value} at ${index} with '${input}'`); console.log(match.groups.color); console.log(match.groups.bird); }
需要多次調(diào)用 regex.exec 方法來遍歷整個搜索結(jié)果集。 在每次迭代期間調(diào)用.exec 時,將顯示下一個結(jié)果(它不會立即返回所有匹配項(xiàng)。),因此使用 while 循環(huán)。
輸出如下:
black*raven at 0 with 'black*raven lime*parrot white*seagull'
black
raven
lime*parrot at 11 with 'black*raven lime*parrot white*seagull'
lime
parrot
white*seagull at 23 with 'black*raven lime*parrot white*seagull'
white
seagull
但奇怪的是:
如果你從這個正則表達(dá)式中刪除 /g,你將永遠(yuǎn)在第一個結(jié)果上創(chuàng)建一個無限循環(huán)。這在過去是一個巨大的痛苦。想象一下,從某個數(shù)據(jù)庫接收正則表達(dá)式時,你不確定它的末尾是否有 /g,你得先檢查一下。
使用 .matchAll() 的好理由
.matchAll() 是如何工作的?
讓我們嘗試匹配單詞 hello
中字母 e
和 l
的所有實(shí)例, 因?yàn)榉祷亓说?,所以可以使?for…of 循環(huán)遍歷它:
// Match all occurrences of the letters: "e" or "l" let iterator = "hello".matchAll(/[el]/); for (const match of iterator) console.log(match);
這一次你可以跳過 /g, .matchall
方法不需要它,結(jié)果如下:
[ 'e', index: 1, input: 'hello' ] // Iteration 1
[ 'l', index: 2, input: 'hello' ] // Iteration 2
[ 'l', index: 3, input: 'hello' ] // Iteration 3
使用 .matchAll() 捕獲組示例:
.matchAll 具有上面列出的所有好處。它是一個迭代器,可以用 for…of 循環(huán)遍歷它,這就是整個語法的不同。
const string = 'black*raven lime*parrot white*seagull'; const regex = /(?.*?)\*(? [a-z0-9]+)/; for (const match of string.matchAll(regex)) { let value = match[0]; let index = match.index; let input = match.input; console.log(`${value} at ${index} with '${input}'`); console.log(match.groups.color); console.log(match.groups.bird); }
請注意已經(jīng)沒有 /g 標(biāo)志,因?yàn)?.matchAll() 已經(jīng)包含了它,打印如下:
black*raven at 0 with 'black*raven lime*parrot white*seagull'
black
raven
lime*parrot at 11 with 'black*raven lime*parrot white*seagull'
lime
parrot
white*seagull at 23 with 'black*raven lime*parrot white*seagull'
white
seagull
也許在美學(xué)上它與原始正則表達(dá)式非常相似,執(zhí)行while循環(huán)實(shí)現(xiàn)。但是如前所述,由于上面提到的許多原因,這是更好的方法,移除 /g 不會導(dǎo)致無限循環(huán)。
動態(tài)導(dǎo)入
現(xiàn)在可以將導(dǎo)入分配給變量:
element.addEventListener('click', async() => { const module = await import(`./api-scripts/button-click.js`); module.clickEvent(); })
Array.flat()
扁平化多維數(shù)組:
let multi = [1,2,3,[4,5,6,[7,8,9,[10,11,12]]]]; multi.flat(); // [1,2,3,4,5,6,Array(4)] multi.flat().flat(); // [1,2,3,4,5,6,7,8,9,Array(3)] multi.flat().flat().flat(); // [1,2,3,4,5,6,7,8,9,10,11,12] multi.flat(Infinity); // [1,2,3,4,5,6,7,8,9,10,11,12]
Array.flatMap()
let array = [1, 2, 3, 4, 5]; array.map(x => [x, x * 2]); let array = [1, 2, 3, 4, 5]; array.map(x => [x, x * 2]);
結(jié)果:
[Array(2), Array(2), Array(2), Array(2), Array(2)]
0: (2) [1, 2]
1: (2) [2, 4]
2: (2) [3, 6]
3: (2) [4, 8]
4: (2) [5, 10]
使用 flatMap
方法:
array.flatMap(v => [v, v * 2]); [1, 2, 2, 4, 3, 6, 4, 8, 5, 10]
Object.fromEntries()
將鍵值對列表轉(zhuǎn)換為對象:
let obj = { apple : 10, orange : 20, banana : 30 }; let entries = Object.entries(obj); entries; (3) [Array(2), Array(2), Array(2)] 0: (2) ["apple", 10] 1: (2) ["orange", 20] 2: (2) ["banana", 30] let fromEntries = Object.fromEntries(entries); { apple: 10, orange: 20, banana: 30 }
String.trimStart() 與 String.trimEnd()
let greeting = " Space around "; greeting.trimEnd(); // " Space around"; greeting.trimStart(); // "Space around ";
格式良好的 JSON.stringify()
此更新修復(fù)了字符 U+D800 到 U+DFFF 的處理,有時可以進(jìn)入 JSON 字符串。 這可能是一個問題,因?yàn)?JSON.stringify 可能會將這些數(shù)字格式化為沒有等效 UTF-8 字符的值, 但 JSON 格式需要 UTF-8
編碼。
解析方法使用格式良好的JSON字符串,如:
'{ “prop1” : 1, "prop2" : 2 }'; // A well-formed JSON format string
注意,要創(chuàng)建正確 JSON 格式的字符串,絕對需要在屬性名周圍加上雙引號。缺少或任何其他類型的引號都不會生成格式良好的JSON。
'{ “prop1” : 1, "meth" : () => {}}'; // Not JSON format string
JSON 字符串格式與 Object Literal 不同,后者看起來幾乎一樣,但可以使用任何類型的引號括住屬性名,也可以包含方法(JSON格式不允許使用方法):
let object_literal = { property: 1, meth: () => {} };
不管怎樣,一切似乎都很好。第一個示例看起來是兼容的。但它們也是簡單的例子,大多數(shù)情況下都能順利地工作!
U+2028 和 U+2029 字符
問題是, ES10 之前的 EcmaScript 實(shí)際上并不完全支持 JSON 格式。前 ES10 時代不接受未轉(zhuǎn)義行分隔符 U+2028 和段落分隔符 U+2029 字符:
對于 U+D800 - U+DFFF 之間的所有字符也是如此
如果這些字符潛入 JSON 格式的字符串(假設(shè)來自數(shù)據(jù)庫記錄),你可能會花費(fèi)數(shù)小時試圖弄清楚為什么程序的其余部分會產(chǎn)生解析錯誤。
因此,如果你傳遞 eval 這樣的字符串 “console.log(' hello ')”
,它將執(zhí)行 JavaScript語句 (通過嘗試將字符串轉(zhuǎn)換為實(shí)際代碼),也類似于 JSON.parse 將處理你的 JSON 字符串的方式。
穩(wěn)定的 Array.prototype.sort()
V8 之前的實(shí)現(xiàn)對包含10個以上項(xiàng)的數(shù)組使用了一種不穩(wěn)定的快速排序算法。
一個穩(wěn)定的排序算法是當(dāng)兩個鍵值相等的對象在排序后的輸出中出現(xiàn)的順序與在未排序的輸入中出現(xiàn)的順序相同時。
但情況不再是這樣了,ES10 提供了一個穩(wěn)定的數(shù)組排序:
var fruit = [ { name: "Apple", count: 13, }, { name: "Pear", count: 12, }, { name: "Banana", count: 12, }, { name: "Strawberry", count: 11, }, { name: "Cherry", count: 11, }, { name: "Blackberry", count: 10, }, { name: "Pineapple", count: 10, } ]; // 創(chuàng)建排序函數(shù): let my_sort = (a, b) => a.count - b.count; // 執(zhí)行穩(wěn)定的ES10排序: let sorted = fruit.sort(my_sort); console.log(sorted);
控制臺輸出(項(xiàng)目以相反的順序出現(xiàn)):
新的Function.toString()
函數(shù)是對象,并且每個對象都有一個 .toString() 方法,因?yàn)樗畛醮嬖谟贠bject.prototype.toString() 上。 所有對象(包括函數(shù))都是通過基于原型的類繼承從它繼承的。
這意味著我們以前已經(jīng)有 funcion.toString() 方法了。
但是 ES10 進(jìn)一步嘗試標(biāo)準(zhǔn)化所有對象和內(nèi)置函數(shù)的字符串表示。 以下是各種新案例:
典型的例子:
function () { console.log('Hello there.'); }.toString();
控制臺輸出(函數(shù)體的字符串格式:)
⇨ function () { console.log('Hello there.'); }
下面是剩下的例子:
直接在方法名 .toString()
Number.parseInt.toString(); ⇨ function parseInt() { [native code] }
綁定上下文:
function () { }.bind(0).toString(); ⇨ function () { [native code] }
內(nèi)置可調(diào)用函數(shù)對象:
Symbol.toString(); ⇨ function Symbol() { [native code] }
動態(tài)生成的函數(shù):
function* () { }.toString(); ⇨ function* () { }
prototype.toString
Function.prototype.toString.call({}); ⇨ Function.prototype.toString requires that 'this' be a Function"
可選的 Catch Binding
在過去,try/catch 語句中的 catch 語句需要一個變量。 try/catch 語句幫助捕獲終端級別的錯誤:
try { // Call a non-existing function undefined_Function undefined_Function("I'm trying"); } catch(error) { // Display the error if statements inside try above fail console.log( error ); // undefined_Function is undefined }
在某些情況下,所需的錯誤變量是未使用的:
try { JSON.parse(text); // <--- this will fail with "text not defined" return true; <--- exit without error even if there is one } catch (redundant_sometmes) <--- this makes error variable redundant { return false; }
編寫此代碼的人通過嘗試強(qiáng)制 true
退出 try 子句。但是,這并不是實(shí)際發(fā)生的情況
(() => { try { JSON.parse(text) return true } catch(err) { return false } })() => false
在 ES10 中,捕獲錯誤的變量是可選的
現(xiàn)在可以跳過錯誤變量:
try { JSON.parse(text); return true; } catch { return false; }
目前還無法測試上一個示例中的 try 語句的結(jié)果,但一旦它出來,我將更新這部分。
標(biāo)準(zhǔn)化 globalThis 對象
這在ES10之前, globalThis 還沒有標(biāo)準(zhǔn)化。
在產(chǎn)品代碼中,你可以自己編寫這個怪物,在多個平臺上“標(biāo)準(zhǔn)化”它:
var getGlobal = function () { if (typeof self !== 'undefined') { return self; } if (typeof window !== 'undefined') { return window; } if (typeof global !== 'undefined') { return global; } throw new Error('unable to locate global object'); };
但即使這樣也不總是奏效。因此,ES10 添加了 globalThis 對象,從現(xiàn)在開始,該對象用于在任何平臺上訪問全局作用域:
// 訪問全局?jǐn)?shù)組構(gòu)造函數(shù) globalThis.Array(0, 1, 2); ⇨ [0, 1, 2] // 類似于 ES5 之前的 window.v = { flag: true } globalThis.v = { flag: true }; console.log(globalThis.v); ⇨ { flag: true }
Symbol.description
description
是一個只讀屬性,它返回 Symbol 對象的可選描述。
let mySymbol = 'My Symbol'; let symObj = Symbol(mySymbol); symObj; // Symbol(My Symbol) symObj.description; // "My Symbol"
Hashbang 語法
也就是 unix 用戶熟悉的 shebang。它指定一個解釋器(什么將執(zhí)行JavaScript文件?)。
ES10標(biāo)準(zhǔn)化,我不會對此進(jìn)行詳細(xì)介紹,因?yàn)閺募夹g(shù)上講,這并不是一個真正的語言特性,但它基本上統(tǒng)一了 JavaScript 在服務(wù)器端的執(zhí)行方式。
$ ./index.js
代替
$ node index.js
ES10類:private、static 和 公共成員
新的語法字符 #octothorpe(hash tag)現(xiàn)在用于直接在類主體的范圍內(nèi)定義變量,函數(shù),getter 和 setter ......以及構(gòu)造函數(shù)和類方法。
下面是一個毫無意義的例子,它只關(guān)注新語法:
class Raven extends Bird { #state = { eggs: 10}; // getter get #eggs() { return state.eggs; } // setter set #eggs(value) { this.#state.eggs = value; } #lay() { this.#eggs++; } constructor() { super(); this.#lay.bind(this); } #render() { /* paint UI */ } }
老實(shí)說,我認(rèn)為這會讓語言更難讀。
代碼部署后可能存在的BUG沒法實(shí)時知道,事后為了解決這些BUG,花了大量的時間進(jìn)行l(wèi)og 調(diào)試,這邊順便給大家推薦一個好用的BUG監(jiān)控工具 Fundebug。
以上就是本文的全部內(nèi)容,希望對大家的學(xué)習(xí)有所幫助,也希望大家多多支持創(chuàng)新互聯(lián)。