做者:Jimmy Breck-McKyejavascript
翻译:疯狂的技术宅前端
原文:www.breck-mckye.com/blog/2019/1…java
未经容许严禁转载web
尽管我在过去 7 年中几乎天天都在写 JavaScript 代码,但不得不认可,我实际上并非很注意 ES 语言的发布声明。 async/await
和 Proxies
之类的主要特性是一回事,可是每一年都有稳定的小规模、渐进式的改进在不断涌现,由于总有一些东西须要学习。正则表达式
因此在本文中,我收集了一些现代 JavaScript 特性,这些特性在首次发布时并无带来太多的关注。其中一些只是编码质量的提升,而另一些确实很方便,能够减小不少代码量。如下是你可能会错过的一些信息:前端工程化
在 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
处理八进制。数据结构
不要与 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
很高兴有一个字面量的语法来表示幂:
2**2 === 4
3**2 === 9
3**3 === 27
复制代码
(这很奇怪,由于我确信 JavaScript 已经有了这个 —— 我可能一直在考虑 Python)
这个功能值得关注,若是你过去几年一直在写 array.indexOf(x)!== -1
这样的代码,那么如今能够用新的 includes
方法:
[1, 2, 3].includes(2) === true
[1, 2, 3].includes(true) === false
复制代码
includes
用 Same 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
这是一对很棒的功能,若是你要与 web workers 一块儿作大量的工做,那么这些特性将被证实是无价的。它们使你能够直接在进程之间共享内存,并经过设置锁来避免资源争抢的状况。
它们都是至关复杂的 API 功能,所以这里不回对其进行概述,可是能够经过 Sitepen 的文章了解更多信息。目前有一些浏览器还不支持,但有望在将来几年内获得改善。
ES2018引入了一整套正则表达式特性:
在支持它的运行时中,你如今能够用正则表达式来进行前向匹配。例如要查找全部以美圆开头的数字:
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`。
我很高兴在 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';
复制代码