你可能錯過的現(xiàn)代 JavaScript 特性
盡管我在過去 7 年中幾乎每天都在寫 JavaScript 代碼,但不得不承認,我實際上并不是很注意 ES 語言的發(fā)布聲明。 async/await 和 Proxies 之類的主要特性是一回事,但是每年都有穩(wěn)定的小規(guī)模、漸進式的改進在不斷涌現(xiàn),因為總有一些東西需要學習。
所以在本文中,我收集了一些現(xiàn)代 JavaScript 特性,這些特性在首次發(fā)布時并沒有帶來太多的關(guān)注。其中一些只是編碼質(zhì)量的提高,而另外一些確實很方便,可以減少很多代碼量。以下是你可能會錯過的一些信息:
ES2015
二進制和八進制
在 JavaScript 中,二進制操作并不常見,但有時也會遇到,否則無法切實解決你的問題。你可能正在為低功耗設(shè)備編寫高性能代碼,將位壓縮到本地存儲中,在瀏覽器中進行像素 RGB 操作,或者必須處理緊密打包的二進制數(shù)據(jù)格式。
這可能意味著有很多工作需要對二進制數(shù)字進行處理,我一直覺得用十進制也能做這些事。好吧,ES6 為此添加了一個二進制數(shù)字格式:0b
- const binaryZero = 0b0;
 - const binaryOne = 0b1;
 - const binary255 = 0b11111111;
 - const binaryLong = 0b111101011101101;
 
這使得處理二進制標志非常容易:
- // Pizza toppings
 - const olives = 0b0001;
 - const ham = 0b0010;
 - const pineapple = 0b0100;
 - const artechoke = 0b1000;
 - const pizza_ham_pineapple = pineapple | ham;
 - const pizza_four_seasons = olives | ham | artechoke;
 
對于八進制數(shù)也是如此。在 JS 世界中,這些領(lǐng)域有點小眾,但在網(wǎng)絡(luò)和某些文件格式中卻很常見?,F(xiàn)在你可以用語法 0o 處理八進制。
Number.isNaN()
不要與 window.isNaN() 混淆,這是一種有著更直觀行為的新方法。
你會發(fā)現(xiàn),經(jīng)典的 isNaN 有一些有趣的怪癖:
- isNaN(NaN) === true
 - isNaN(null) === false
 - isNaN(undefined) === true
 - isNaN({}) === true
 - isNaN('0/0') === true
 - isNaN('hello') === true
 
是什么導(dǎo)致了這種結(jié)果?首先,這些參數(shù)實際上都不是 NaN。與以往一樣,問題出在大家“最喜歡的” JavaScript 特性上:類型強制。通過 Number 函數(shù)將 window.isNaN 的參數(shù)強制為數(shù)字。
好吧,新的 Number.isNaN() 靜態(tài)方法解決了所有問題。它會一勞永逸地返回你提供的自變量與 NaN 的相等性。這是絕對明確的:
- Number.isNaN(NaN) === true
 - Number.isNaN(null) === false
 - Number.isNaN(undefined) === false
 - Number.isNaN({}) === false
 - Number.isNaN('0/0') === false
 - Number.isNaN('hello') === false
 
函數(shù)簽名: Number.isNaN : (value: any) => boolean
ES2016
指數(shù)(冪)運算符
很高興有一個字面量的語法來表示冪:
- 2**2 === 4
 - 3**2 === 9
 - 3**3 === 27
 
(這很奇怪,因為我確信 JavaScript 已經(jīng)有了這個 —— 我可能一直在考慮 Python)
Array.prototype.includes()
這個功能值得關(guān)注,如果你過去幾年一直在寫 array.indexOf(x)!== -1 這樣的代碼,那么現(xiàn)在可以用新的 includes 方法:
- [1, 2, 3].includes(2) === true
 - [1, 2, 3].includes(true) === false
 
includes 用 Same Value Zero Algorithm(幾乎與嚴格等式 === 相同)進行檢查,但它可以處理 NaN 值。像相等檢查一樣,它將通過引用而不是內(nèi)容來比較對象:
- const object1 = {};
 - const object2 = {};
 - const array = [object1, 78, NaN];
 - array.includes(object1) === true
 - array.includes(object2) === false
 - array.includes(NaN) === true
 
includes 可以通過第二個參數(shù) fromIndex 讓你提供一個偏移量:
- // positions 0 1 2 3 4
 - const array = [1, 1, 1, 2, 2];
 - array.includes(1, 2) === true
 - array.includes(1, 3) === false
 
太順手了。
函數(shù)簽名: Array.prototype.includes : (match: any, offset?: Int) => boolean
ES2017
共享數(shù)組緩沖區(qū)和原子操作
這是一對很棒的功能,如果你要與 web workers 一起做大量的工作,那么這些特性將被證明是無價的。它們使你可以直接在進程之間共享內(nèi)存,并通過設(shè)置鎖來避免資源爭搶的情況。
它們都是相當復(fù)雜的 API 功能,因此這里不回對其進行概述,但是可以通過 Sitepen 的文章了解更多信息。目前有一些瀏覽器還不支持,但有望在未來幾年內(nèi)得到改善。
ES2018
強大的正則表達式
ES2018引入了一整套正則表達式特性:
Lookbehind 匹配項(前向匹配)
在支持它的運行時中,你現(xiàn)在可以用正則表達式來進行前向匹配。例如要查找所有以美元開頭的數(shù)字:
- const regex = /(?<=\$)\d+/;
 - const text = 'This cost $400';
 - text.match(regex) === ['400']
 
關(guān)鍵是新的 lookbehind 搜索組與lookahead 搜索組是一對邪惡的雙胞胎:
- Look ahead: (?=abc)
 - Look behind: (?<=abc)
 - Look ahead negative: (?!abc)
 - Look behind negative: (?<!abc)
 
不幸的是,目前還沒有什么方法可以為較舊的瀏覽器支持新的后向語法,所以你目前只能在 Node 上用它。
你可以命名捕獲組
正則表達式真正強大的功能是能夠挑選出子匹配項,并用它們進行一些簡單的解析。但是直到不久前,我們只能通過數(shù)字來引用子匹配項,例如:
- const getNameParts = /(\w+)\s+(\w+)/g;
 - const name = "Weyland Smithers";
 - const subMatches = getNameParts.exec(name);
 - subMatches[1] === 'Weyland'
 - subMatches[2] === 'Smithers'
 
現(xiàn)在有了一種語法,可以通過在要命名的每個組的括號的開頭放置 ? 來分配這些子匹配項(或捕獲組)的名稱:
- const getNameParts = /(?<first>\w+)\s(?<last>\w+)/g;
 - const name = "Weyland Smithers";
 - const subMatches = getNameParts.exec(name);
 - const {first, last} = subMatches.groups
 - first === 'Weyland'
 - last === 'Smithers'
 
不幸的是,目前暫時只有 Chrome 和 Node 支持。
現(xiàn)在可以用點匹配新行
你只需要提供 /s 標志,例如 /someRegex./s、`/anotherRegex./sg。
ES2019
Array.prototype.flat() & flatMap()
我很高興在 MDN 上看到這些內(nèi)容。
簡單地說,flat() 將多維數(shù)組按指定的最大 depth 展平:
- const multiDimensional = [
 - [1, 2, 3],
 - [4, 5, 6],
 - [7,[8,9]]
 - ];
 - multiDimensional.flat(2) === [1, 2, 3, 4, 5, 6, 7, 8, 9]
 
flatMap 本質(zhì)上是一個 map,也是深度為 1 的 flat。當從映射函數(shù)返回一個數(shù)組,但你不希望結(jié)果為嵌套數(shù)據(jù)結(jié)構(gòu)時,用它很方便:
- const texts = ["Hello,", "today I", "will", "use FlatMap"];
 - // with a plain map
 - const mapped = texts.map(text => text.split(' '));
 - mapped === ['Hello', ['today', 'I'], 'will', ['use', 'FlatMap']];
 - // with flatmap
 - const flatMapped = texts.flatMap(text => text.split(' '));
 - flatMapped === ['Hello', 'today', 'I', 'will', 'use', 'FlatMap'];
 
未綁定的捕獲
現(xiàn)在你可以編寫 try/catch 語句,而不必綁定拋出的錯誤:
- try {
 - // something throws
 - } catch {
 - // don't have to do catch(e)
 - }
 
順便說一句,對你不關(guān)心的 e 的值的捕獲行為,有時稱為 Pokémon 異常處理。 ‘因為你要捕獲所有的’!
字符串修剪方法
很小但是很好用:
- const padded = ' Hello world ';
 - padded.trimStart() === 'Hello world ';
 - padded.trimEnd() === ' Hello world';
 















 
 
 









 
 
 
 