ES10 特性的完整指南小结


Posted in Javascript onMarch 04, 2019

本篇文章主要介绍了ES10 特性的完整指南,分享给大家,具体如下:

ES10 特性的完整指南小结

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 一起使用或者带有 /g 的 RegExp.exec 或者带有 /g 的 RegExp.test 。

首先,让我们看看旧规范是如何工作的。

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

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

结果是单个 "l"(注意:匹配存储在 matches[0] 中而不是 matches)

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

将 string.match 与 regex 参数一起使用也是如此:

让我们使用正则表达式 /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() 的好理由

  • 在与捕获组一起使用时,它可以更加优雅,捕获组只是使用 () 提取模式的正则表达式的一部分。
  • 它返回一个迭代器而不是一个数组,迭代器本身是有用的。
  • 迭代器可以使用扩展运算符 (…) 转换为数组。
  • 它避免了带有 /g 标志的正则表达式,当从数据库或外部源检索未知正则表达式并与陈旧的RegEx 对象一起使用时,它非常有用。
  • 使用 RegEx 对象创建的正则表达式不能使用点 (.) 操作符链接。
  • 高级: 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+D800 到 U+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 特性的完整指南小结

新的Function.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。

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

Javascript 相关文章推荐
JavaScript动态创建div属性和样式示例代码
Oct 09 Javascript
jQuery之字体大小的设置方法
Feb 27 Javascript
js监听鼠标事件控制textarea输入字符串的个数
Sep 29 Javascript
jQuery简单操作cookie的插件实例
Jan 13 Javascript
神奇!js+CSS+DIV实现文字颜色渐变效果
Mar 16 Javascript
JS对HTML表格进行增删改操作
Aug 22 Javascript
给easyui datebox扩展一个清空的实例
Nov 09 Javascript
es6 字符串String的扩展(实例讲解)
Aug 03 Javascript
React.js绑定this的5种方法(小结)
Jun 05 Javascript
JS实现根据详细地址获取经纬度功能示例
Apr 16 Javascript
jQuery实现鼠标滑动切换图片
May 27 jQuery
原生js实现弹窗消息动画
Nov 20 Javascript
node.js使用express框架进行文件上传详解
Mar 03 #Javascript
微信小程序新手教程之启动页的重要性
Mar 03 #Javascript
微信小程序新手教程之页面打开数量限制
Mar 03 #Javascript
JS实现的冒泡排序,快速排序,插入排序算法示例
Mar 02 #Javascript
JS+php后台实现文件上传功能详解
Mar 02 #Javascript
JS事件绑定的常用方式实例总结
Mar 02 #Javascript
JS实现获取数组中最大值或最小值功能示例
Mar 02 #Javascript
You might like
3种平台下安装php4经验点滴
2006/10/09 PHP
用PHP制作静态网站的模板框架(一)
2006/10/09 PHP
php类自动加载器实现方法
2015/07/28 PHP
YII框架关联查询操作示例
2019/04/29 PHP
PHP实现微信提现功能(微信商城)
2019/11/21 PHP
QUnit jQuery的TDD框架
2010/11/04 Javascript
jQuery为iframe的body添加click事件的实现代码
2011/04/07 Javascript
IE下JS读取xml文件示例代码
2013/08/05 Javascript
js与C#进行时间戳转换
2014/11/14 Javascript
基于javascript实现动态时钟效果
2020/08/18 Javascript
使用vue.js开发时一些注意事项
2016/04/27 Javascript
初探nodeJS
2017/01/24 NodeJs
用户管理的设计_jquery的ajax实现二级联动效果
2017/07/13 jQuery
Vue基于NUXT的SSR详解
2017/10/24 Javascript
JS中offset和匀速动画详解
2018/02/06 Javascript
Vue.js实现可配置的登录表单代码详解
2018/03/29 Javascript
jquery获取元素到屏幕四周可视距离的方法
2018/09/05 jQuery
jquery实现直播视频弹幕效果
2020/02/25 jQuery
Vue 实例中使用$refs的注意事项
2021/01/29 Vue.js
利用python发送和接收邮件
2016/09/27 Python
python实现简单中文词频统计示例
2017/11/08 Python
详解PyCharm配置Anaconda的艰难心路历程
2018/08/13 Python
python3 打开外部程序及关闭的示例
2018/11/06 Python
浅析Python 读取图像文件的性能对比
2019/03/07 Python
python定时复制远程文件夹中所有文件
2019/04/30 Python
Django基础知识 web框架的本质详解
2019/07/18 Python
Python 转换RGB颜色值的示例代码
2019/10/13 Python
什么是python的自省
2020/06/21 Python
J.Crew官网:美国知名休闲服装品牌
2017/05/19 全球购物
杰夫·班克斯男士服装网上商店:Jeff Banks
2019/10/24 全球购物
创意爱尔兰礼物:Creative Irish Gifts
2020/01/29 全球购物
大学生咖啡店创业计划书
2014/01/21 职场文书
中式婚礼主持词
2014/03/13 职场文书
励志演讲稿200字
2014/08/21 职场文书
Python实现随机生成迷宫并自动寻路
2021/06/13 Python
Sentry的安装、配置、使用教程(Sentry日志手机系统)
2022/07/23 Python