你可能錯過的現代 JavaScript 特性

作者:Jimmy Breck-McKye

翻譯:瘋狂的技術宅

原文:http://www.breck-mckye.com/bl...

未經允許嚴禁轉載

儘管我在過去 7 年中幾乎每天都在寫 JavaScript 代碼,但不得不承認,我實際上並不是很注意 ES 語言的發佈聲明。 async/awaitProxies 之類的主要特性是一回事,但是每年都有穩定的小規模、漸進式的改進在不斷涌現,因爲總有一些東西需要學習。

所以在本文中,我收集了一些現代 JavaScript 特性,這些特性在首次發佈時並沒有帶來太多的關注。其中一些只是編碼質量的提高,而另外一些確實很方便,可以減少很多代碼量。以下是你可能會錯過的一些信息:

ES2015

二進制和八進制

在 JavaScript 中,二進制操作並不常見,但有時也會遇到,否則無法切實解決你的問題。你可能正在爲低功耗設備編寫高性能代碼,將位壓縮到本地存儲中,在瀏覽器中進行像素 RGB 操作,或者必須處理緊密打包的二進制數據格式。

這可能意味着有很多工作需要對二進制數字進行處理,我一直覺得用十進制也能做這些事。好吧,ES6 爲此添加了一個二進制數字格式: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;

對於八進制數也是如此。在 JS 世界中,這些領域有點小衆,但在網絡和某些文件格式中卻很常見。現在你可以用語法 0o 處理八進制。

Number.isNaN()

不要與 window.isNaN() 混淆,這是一種有着更直觀行爲的新方法。

你會發現,經典的 isNaN 有一些有趣的怪癖:

isNaN(NaN)              === true
isNaN(null)             === false
isNaN(undefined)        === true
isNaN({})               === true
isNaN('0/0')            === true
isNaN('hello')          === true

是什麼導致了這種結果?首先,這些參數實際上都不是 NaN。與以往一樣,問題出在大家“最喜歡的” JavaScript 特性上:類型強制。通過 Number 函數將 window.isNaN 的參數強制爲數字。

好吧,新的 Number.isNaN() 靜態方法解決了所有問題。它會一勞永逸地返回你提供的自變量與 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

函數簽名: Number.isNaN : (value: any) => boolean

ES2016

指數(冪)運算符

很高興有一個字面量的語法來表示冪:

2**2 === 4
3**2 === 9
3**3 === 27

(這很奇怪,因爲我確信 JavaScript 已經有了這個 —— 我可能一直在考慮 Python)

Array.prototype.includes()

這個功能值得關注,如果你過去幾年一直在寫 array.indexOf(x)!== -1 這樣的代碼,那麼現在可以用新的 includes 方法:

[1, 2, 3].includes(2)    === true
[1, 2, 3].includes(true) === false

includesSame Value Zero Algorithm(幾乎與嚴格等式 === 相同)進行檢查,但它可以處理 NaN 值。像相等檢查一樣,它將通過引用而不是內容來比較對象:

const object1 = {};
const object2 = {};

const array = [object1, 78, NaN];

array.includes(object1) === true
array.includes(object2) === false
array.includes(NaN)     === true

includes 可以通過第二個參數 fromIndex 讓你提供一個偏移量:

// positions   0  1  2  3  4
const array = [1, 1, 1, 2, 2];

array.includes(1, 2) === true
array.includes(1, 3) === false

太順手了。

函數簽名: Array.prototype.includes : (match: any, offset?: Int) => boolean

ES2017

共享數組緩衝區和原子操作

這是一對很棒的功能,如果你要與 web workers 一起做大量的工作,那麼這些特性將被證明是無價的。它們使你可以直接在進程之間共享內存,並通過設置鎖來避免資源爭搶的情況。

它們都是相當複雜的 API 功能,因此這裏不回對其進行概述,但是可以通過 Sitepen 的文章瞭解更多信息。目前有一些瀏覽器還不支持,但有望在未來幾年內得到改善。

ES2018

強大的正則表達式

ES2018引入了一整套正則表達式特性:

Lookbehind 匹配項(前向匹配)

在支持它的運行時中,你現在可以用正則表達式來進行前向匹配。例如要查找所有以美元開頭的數字:

const regex = /(?<=\$)\d+/;
const text  = 'This cost $400';
text.match(regex) === ['400']

關鍵是新的 lookbehind 搜索組與lookahead 搜索組是一對邪惡的雙胞胎:

Look ahead:  (?=abc)
Look behind: (?<=abc)

Look ahead negative:  (?!abc)
Look behind negative: (?<!abc)

不幸的是,目前還沒有什麼方法可以爲較舊的瀏覽器支持新的後向語法,所以你目前只能在 Node 上用它。

你可以命名捕獲組

正則表達式真正強大的功能是能夠挑選出子匹配項,並用它們進行一些簡單的解析。但是直到不久前,我們只能通過數字來引用子匹配項,例如:

const getNameParts  = /(\w+)\s+(\w+)/g;
const name          = "Weyland Smithers";
const subMatches    = getNameParts.exec(name);

subMatches[1]     === 'Weyland'
subMatches[2]     === 'Smithers'

現在有了一種語法,可以通過在要命名的每個組的括號的開頭放置 ? 來分配這些子匹配項(或捕獲組)的名稱:

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 支持。

現在可以用點匹配新行

你只需要提供 /s 標誌,例如 /someRegex./s`/anotherRegex./sg

ES2019

Array.prototype.flat() & flatMap()

我很高興在 MDN 上看到這些內容。

簡單地說,flat() 將多維數組按指定的最大 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 本質上是一個 map,也是深度爲 1 的 flat。當從映射函數返回一個數組,但你不希望結果爲嵌套數據結構時,用它很方便:

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'];

未綁定的捕獲

現在你可以編寫 try/catch 語句,而不必綁定拋出的錯誤:

try {
  // something throws
} catch {
  // don't have to do catch(e)
}

順便說一句,對你不關心的 e 的值的捕獲行爲,有時稱爲 Pokémon 異常處理。 ‘因爲你要捕獲所有的’!

字符串修剪方法

很小但是很好用:

const padded         = '          Hello world   ';
padded.trimStart() === 'Hello world   ';
padded.trimEnd()   === '          Hello world';

本文首發微信公衆號:前端先鋒

歡迎掃描二維碼關注公衆號,每天都給你推送新鮮的前端技術文章

歡迎掃描二維碼關注公衆號,每天都給你推送新鮮的前端技術文章

歡迎繼續閱讀本專欄其它高贊文章:


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章