ES10 特征的完全指南

《ES10 特征的完全指南》

想浏览更多优良文章请猛戳GitHub博客,一年百来篇优良文章等着你!

ES10 还只是一个草案。然则除了 Object.fromEntries 以外,Chrome 的大多数功用都已完成了,为何不早点最先探究呢?当统统浏览器都最先支撑它时,你将走在前面,这只是时候题目。

在新的言语特征方面,ES10 不如 ES6 主要,但它确切增加了一些风趣的特征(个中一些功用如今还没法在浏览器中事情: 2019/02/21)

在 ES6 中,箭头函数无疑是最受迎接的新特征,在 ES10 中会是什么呢?

《ES10 特征的完全指南》

BigInt -恣意精度整数

BigInt 是第七种 原始范例。

BigInt 是一个恣意精度的整数。这意味着变量如今能够 示意²⁵³ 数字,而不仅仅是9007199254740992

const b = 1n;  // 追加 n 以建立 BigInt

在过去,不支撑大于 9007199254740992 的整数值。假如凌驾,该值将锁定为 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'

即是运算符可用于两种范例之间比较:

10n === BigInt(10);
⇨ true
10n == 10;
⇨ true

数学运算符只能在自身的范例中事情:

200n / 10n
⇨ 20n
200n / 20
⇨ Uncaught TypeError:
   Cannot mix BigInt and other types, use explicit conversions <

-运算符能够操纵, + 不可用

-100n
⇨ -100n
+100n
⇨ Uncaught TypeError:
  Cannot convert a BigInt value to a number


当你读到这篇文章的时刻,matchAll 能够已在 Chrome C73 中正式完成了——假如不是,它依然值得一看。特别是假如你是一个正则表达式(regex)爱好者。

string.prototype.matchAll()

假如您运转谷歌搜刮JavaScript string match all,第一个效果将是如许的:怎样编写正则表达式“match all”?

最好效果将发起 String.match 与正则表达式和 /g 一同运用或许带有 /gRegExp.exec 或许带有 /gRegExp.test

起首,让我们看看旧范例是怎样事情的。

带字符串参数的 String.match 仅返回第一个婚配:

let string = 'Hello';
let matches = string.match('l');
console.log(matches[0]); // "l"

效果是单个 "l"(注重:婚配存储在 matches[0] 中而不是 matches)

“hello”中搜刮 "l" 只返回 "l"

string.matchregex 参数一同运用也是云云:

让我们运用正则表达式 /l/ 找到字符 串“hello” 中的 “l” 字符:

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”, “l”];

很好,我们运用 < ES10 体式格局得到了多个婚配,它一向起作用。

那末为何要运用全新的 matchAll 要领呢? 在我们更细致地回复这个题目之前,让我们先来看看 捕获组。假如不出不测,你能够会学到一些关于正则表达式的新知识。

正则表达式捕获组

在 regex 中捕获组只是从 () 括号中提取一个形式,能够运用 /regex/.exec(string)string.match 捕获组。

通例捕获组是经由过程将形式包装在 (pattern) 中建立的,然则要在效果对象上建立 groups 属性,它是: (?<name>pattern)

要建立一个新的组名,只需在括号内附加 ?<name>,效果中,分组 (pattern) 婚配将成为 group.name,并附加到 match 对象,以下是一个实例:

字符串标本婚配:

《ES10 特征的完全指南》

这里建立了 match.groups.color 和 match.groups.bird

const string = 'black*raven lime*parrot white*seagull';
const regex = /(?<color>.*?)\*(?<bird>[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);
}

须要屡次挪用 regex.exec 要领来遍历全部搜刮效果集。 在每次迭代时期挪用.exec 时,将显现下一个效果(它不会马上返回统统婚配项。),因而运用 while 轮回。

输出以下:

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

但奇怪的是:

假如你从这个正则表达式中删除
/g,你将永远在第一个效果上建立一个无穷轮回。这在过去是一个庞大的痛楚。设想一下,从某个数据库吸收正则表达式时,你不确定它的末端是不是有
/g,你得先检查一下。

运用 .matchAll() 的好来由

  1. 在与捕获组一同运用时,它能够越发文雅,捕获组只是运用 () 提取形式的正则表达式的一部份。
  2. 返回一个迭代器而不是一个数组,迭代器自身是有效的。
  3. 迭代器能够运用扩大运算符 (…) 转换为数组。
  4. 它避免了带有 /g 标志的正则表达式,当从数据库或外部源检索未知正则表达式并与陈腐的RegEx 对象一同运用时,它异常有效。
  5. 运用 RegEx 对象建立的正则表达式不能运用点 (.) 操纵符链接。
  6. 高等: RegEx 对象变动跟踪末了婚配位置的内部 .lastindex 属性,这在庞杂的状况下会形成严重破坏。

.matchAll() 是怎样事情的?

让我们尝试婚配单词 hello 中字母 el 的统统实例, 因为返回了迭代器,所以能够运用 for…of 轮回遍历它:

// Match all occurrences of the letters: "e" or "l" 
let iterator = "hello".matchAll(/[el]/);
for (const match of iterator)
    console.log(match);

这一次你能够跳过 /g.matchall 要领不须要它,效果以下:

[ '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 轮回遍历它,这就是全部语法的差别。

const string = 'black*raven lime*parrot white*seagull';
const regex = /(?<color>.*?)\*(?<bird>[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);
}

请注重已没有 /g 标志,因为 .matchAll() 已包含了它,打印以下:

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

或许在美学上它与原始正则表达式异常类似,实行while轮回完成。然则如前所述,因为上面提到的很多缘由,这是更好的要领,移除 /g 不会致使无穷轮回。

动态导入

如今能够将导入分配给变量:

element.addEventListener('click', async() => {
  const module = await import(`./api-scripts/button-click.js`);
  module.clickEvent();
})

Array.flat()

扁平化多维数组:

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

效果:

[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()

将键值对列表转换为对象:

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()

此更新修复了字符 U+D800U+DFFF 的处置惩罚,偶然能够进入 JSON 字符串。 这多是一个题目,因为 JSON.stringify 能够会将这些数字花样化为没有等效 UTF-8 字符的值, 但 JSON 花样须要 UTF-8 编码。

剖析要领运用花样优越的JSON字符串,如:

'{ “prop1” : 1, "prop2" : 2 }'; // A well-formed JSON format string

注重,要建立准确 JSON 花样的字符串,相对须要在属性名四周加上双引号。缺乏或任何其他范例的引号都不会天生花样优越的JSON。

'{ “prop1” : 1, "meth" : () => {}}'; // Not JSON format string

JSON 字符串花样与 Object Literal 差别,后者看起来险些一样,但能够运用任何范例的引号括住属性名,也能够包含要领(JSON花样不允许运用要领):

let object_literal = { property: 1, meth: () => {} };

不管怎样,统统好像都很好。第一个示例看起来是兼容的。但它们也是简朴的例子,大多数状况下都能顺遂地事情!

U+2028 和 U+2029 字符

题目是, ES10 之前的 EcmaScript 现实上并不完整支撑 JSON 花样。前 ES10 时期不接受未转义行分隔符 U+2028 和段落分隔符 U+2029 字符:

《ES10 特征的完全指南》

《ES10 特征的完全指南》

关于 U+D800 – U+DFFF 之间的统统字符也是云云

假如这些字符潜入 JSON 花样的字符串(假定来自数据库纪录),你能够会消费数小时试图弄清楚为何递次的其余部份会发作剖析毛病。

因而,假如你通报 eval 如许的字符串 “console.log(' hello ')”,它将实行 JavaScript语句 (经由过程尝试将字符串转换为现实代码),也类似于 JSON.parse 将处置惩罚你的 JSON 字符串的体式格局。

稳固的 Array.prototype.sort()

V8 之前的完成对包含10个以上项的数组运用了一种不稳固的疾速排序算法。

一个稳固的排序算法是当两个键值相称的对象在排序后的输出中涌现的递次与在未排序的输入中涌现的递次相同时。

但状况不再是如许了,ES10 供应了一个稳固的数组排序:

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, }
];
// 建立排序函数:
let my_sort = (a, b) => a.count - b.count;
// 实行稳固的ES10排序:
let sorted = fruit.sort(my_sort);
console.log(sorted);

控制台输出(项目以相反的递次涌现):

《ES10 特征的完全指南》

新的F unction.toString()

函数是对象,而且每一个对象都有一个 .toString() 要领,因为它最初存在于Object.prototype.toString() 上。 统统对象(包含函数)都是经由过程基于原型的类继续从它继续的。

这意味着我们之前已有 funcion.toString() 要领了。

然则 ES10 进一步尝试标准化统统对象和内置函数的字符串示意。 以下是种种新案例:

典范的例子:

function () { console.log('Hello there.'); }.toString();

控制台输出(函数体的字符串花样:)

⇨ function () { console.log('Hello there.'); }

下面是剩下的例子:

直接在要领名 .toString()

Number.parseInt.toString();
⇨ function parseInt() { [native code] }

绑定上下文:

function () { }.bind(0).toString();
⇨ function () { [native code] }

内置可挪用函数对象:

Symbol.toString();
⇨ function Symbol() { [native code] }

动态天生的函数:

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;
}

编写此代码的人经由过程尝试强迫 true 退出 try 子句。然则,这并非现实发作的状况

(() => {
    try {
        JSON.parse(text)
        return true
    } catch(err) {
        return false
    }
})()
=> false

在 ES10 中,捕获毛病的变量是可选的

如今能够跳过毛病变量:

try {
    JSON.parse(text);
    return true;
}
catch
{
    return false;
}

如今还没法测试上一个示例中的 try 语句的效果,但一旦它出来,我将更新这部份。

标准化 globalThis 对象

这在ES10之前, globalThis 还没有标准化。

在产品代码中,你能够自身编写这个怪物,在多个平台上“标准化”它:

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 对象,从如今最先,该对象用于在任何平台上接见全局作用域:

// 接见全局数组组织函数
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。它指定一个诠释器(什么将实行JavaScript文件?)。

ES10标准化,我不会对此举行细致引见,因为从手艺上讲,这并非一个真正的言语特征,但它基本上一致了 JavaScript 在服务器端的实行体式格局。

$ ./index.js

替代

$ node index.js

ES10类:private、static 和 大众成员

新的语法字符 #octothorpe(hash tag)如今用于直接在类主体的范围内定义变量,函数,getter 和 setter ……以及组织函数和类要领。

下面是一个毫无意义的例子,它只关注新语法:

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 */
    }
}

老实说,我以为这会让言语更难读。

代码布置后能够存在的BUG没法及时晓得,预先为了处理这些BUG,花了大批的时候举行log 调试,这边顺便给人人引荐一个好用的BUG监控东西 Fundebug

原文:

https://medium.freecodecamp.o…

你的点赞是我延续分享好东西的动力,迎接点赞!

交换

干货系列文章汇总以下,以为不错点个Star,迎接 加群 互相进修。

https://github.com/qq44924588…

我是小智,民众号「大迁天下」作者,对前端手艺坚持进修爱好者。我会常常分享自身所学所看的干货,在进阶的路上,共勉!

关注民众号,背景复兴福利,即可看到福利,你懂的。

《ES10 特征的完全指南》

    原文作者:前端小智
    原文地址: https://segmentfault.com/a/1190000018311280
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞