20多个小事例带你重温ES10新特性(小结)


Posted in Javascript onSeptember 29, 2019

ES10 虽然没有像 ES6 那么多新特性,但 ES10 仍然有一些有用的特性。文本通过简单示例来介绍了 ES10 新出来的特性。通过这种方式,咱们就可以快速理解,而不需要看太多的官方解释。

ES10 新特性主要如下:

  • 数组方法:flat和flatMap
  • Object.fromEntries
  • 字符串方法:trimStart 和 trimEnd
  • Symbol 的 description 属性
  • try { } catch {} // catch 的参数可以省略了
  • JSON ⊂ ECMAScript (让 ECMAScript 兼容所有 JSON 支持的文本)
  • 格式良好的 JSON.stringify()
  • 稳定的 Array.prototype.sort()
  • 修正后的 Function.toString
  • BigInt 是第七种 原始类型
  • 动态导入
  • 标准化 globalThis 对象

1. Array.flat() && Array.flatMap

Array.flat() 方法会按照一个可指定的深度递归遍历数组,并将所有元素与遍历到的子数组中的元素合并为一个新数组返回。

Array.flatMap() 方法首先使用映射函数映射每个元素,然后将结果压缩成一个新数组。它与 map 和 深度值1的 flat 几乎相同,但 flatMap 通常在合并成一种方法的效率稍微高一些。

事例一:

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

array 现在的结果:

[Array(2), Array(2), Array(2)]
0: (2)[1, 2]
1: (2)[2, 4]
2: (2)[3, 6]

使用 flatMap 方式:

array.flatMap(v => [v, v * 2]);
[1, 2, 2, 4, 3, 6, 4, 8, 5, 10]

综合示例:

20多个小事例带你重温ES10新特性(小结)

2.Object.fromEntries()

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 }

事例二:

20多个小事例带你重温ES10新特性(小结)

3.String.protype.matchAll

早期的一个问题是,如何编写正则表达式“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

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

那么为什么要使用全新的 matchAll 方法呢? 在解疑这个问题之前,先来看看 捕获组。

正则表达式捕获组

regex 中捕获组只是从 () 括号中提取一个模式,可以使用 /regex/.exec(string)string.match 捕捉组。

常规捕获组是通过将模式包装在 (pattern) 中创建的,但是要在结果对象上创建 groups 属性,它是: (?<name>pattern)

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

字符串标本匹配:

20多个小事例带你重温ES10新特性(小结)

这里创建了 match.groups.colormatch.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() 捕获组示例:

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 不会导致无限循环。

综合事例:

20多个小事例带你重温ES10新特性(小结)

4.String.trimStart() 与 String.trimEnd()

trimStart() :删除字符串的开头空格。

trimEnd() :删除字符串末尾的空格。

事例一:

let greeting = "   Space around   ";
greeting.trimEnd();  // "   Space around";
greeting.trimStart(); // "Space around   ";

事例二:

20多个小事例带你重温ES10新特性(小结)

5.Symbol.Description

description 是一个只读属性,它会返回 Symbol 对象的可选描述的字符串。

事例一:

let mySymbol = 'My Symbol';
let symObj = Symbol(mySymbol);
symObj; // Symbol(My Symbol)
symObj.description; // "My Symbol"

事例二:

20多个小事例带你重温ES10新特性(小结)

6.catch 的参数可以省略

在过去,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;
}

在 ES10 中,捕获错误的变量是可选的,现在可以跳过错误变量:

事例一:

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

事例二:

20多个小事例带你重温ES10新特性(小结)

7. JSON ⊂ ECMAScript

什么是 JSON 超集?还记得 这个符号的可以这样解释该提案 JSON ⊂ ECMAScript,简而言之就是让 ECMAScript 兼容所有 JSON 支持的文本。ECMAScript 曾在标准 JSON.parse 部分阐明 JSON 确为其一个子集,但由于 JSON 内容可以正常包含 U+2028 行分隔符与 U+2029 段落分隔符而 ECMAScript 却不行。

该草案旨在解决这一问题。在这之前,如果你使用 JSON.parse() 执行带如上特殊字符的字符串时,只会收到 SyntaxError 的错误提示。该草案同样是向后兼容的,其对用户唯一的影响是保持原样,即在暂不支持特殊字符解析的运行环境中保持 SyntaxError 的报错。

20多个小事例带你重温ES10新特性(小结)

8.格式良好的 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 字符:

20多个小事例带你重温ES10新特性(小结)

对于 U+D800 - U+DFFF 之间的所有字符也是如此

如果这些字符潜入 JSON 格式的字符串(假设来自数据库记录),你可能会花费数小时试图弄清楚为什么程序的其余部分会产生解析错误。

因此,如果你传递 eval 这样的字符串 “console.log(' hello ')”,它将执行 JS语句 (通过尝试将字符串转换为实际代码),也类似于 JSON.parse 将处理你的 JSON 字符串的方式。

ES10建议的解决方案是将未配对的代理代码点表示为JSON转义序列,而不是将它们作为单个UTF-16代码单元返回。

20多个小事例带你重温ES10新特性(小结)

9.稳定的 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);

控制台输出(项目以相反的顺序出现):

20多个小事例带你重温ES10新特性(小结)

事例二:

20多个小事例带你重温ES10新特性(小结)

10.新的 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"

20多个小事例带你重温ES10新特性(小结)

11.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

20多个小事例带你重温ES10新特性(小结)

12.动态导入

动态导入返回请求模块的模块名称空间对象的promise 。因此,可以配合使用async/await

事例一:

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

事例二:

20多个小事例带你重温ES10新特性(小结)

13.标准化 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 对象,从现在开始,该对象用于在任何平台上访问全局作用域:

但即使这样也不总是奏效。因此,ES10 添加了 globalThis 对象,从现在开始,该对象用于在任何平台上访问全局作用域:

20多个小事例带你重温ES10新特性(小结)

总结

JS 是一种动态语言,这对 web 开发非常有益。自 2015 年 ES6 出现以来,JS 语言经历了一次充满活力的演变。在这篇文章中,咱们回顾了ES10(2019)中出现的特性,并介绍了一些将在ES11(2020)中保持稳定的特性,因为它们处于state 3,并且很可能在下一个版本中被标准化。

尽管这些特性中的许多对于Web应用程序的开发可能不是必需的,但是一些特性可以规制咱们以前通过技巧或大量冗长实现的代码。

代码部署后可能存在的BUG没法实时知道,事后为了解决这些BUG,花了大量的时间进行log 调试,这边顺便给大家推荐一个好用的BUG监控工具 Fundebug。

原文:https://dev.to/carlillo/12-es10-features-in-12-simple-examples-2cbn

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

Javascript 相关文章推荐
javascript 事件查询综合 推荐收藏
Mar 10 Javascript
事件冒泡是什么如何用jquery阻止事件冒泡
Mar 20 Javascript
当json键为数字时的取值方法解析
Nov 15 Javascript
浅谈 jQuery 事件源码定位问题
Jun 18 Javascript
Jquery uploadify上传插件使用详解
Jan 13 Javascript
Javascript将双字节字符转换成单字节字符并计算长度
Jun 22 Javascript
javascript 初学教程及五子棋小程序的简单实现
Jul 04 Javascript
Vue父子模版传值及组件传值的三种方法
Nov 27 Javascript
解决vue中对象属性改变视图不更新的问题
Feb 23 Javascript
Jquery的autocomplete插件用法及参数讲解
Mar 12 jQuery
深入学习TypeScript 、React、 Redux和Ant-Design的最佳实践
Jun 17 Javascript
在vue中对数组值变化的监听与重新响应渲染操作
Jul 17 Javascript
解决layui页面按钮点击无反应,也不报错的问题
Sep 29 #Javascript
react用Redux中央仓库实现一个todolist
Sep 29 #Javascript
layui数据表格 table.render 报错的解决方法
Sep 29 #Javascript
JavaScript实现秒杀时钟倒计时
Sep 29 #Javascript
在layui中对table中的数据进行判断(0、1)转换为提示信息的方法
Sep 28 #Javascript
layui+jquery支持IE8的表格分页方法
Sep 28 #jQuery
JavaScript获取页面元素的常用方法详解
Sep 28 #Javascript
You might like
PHP 强制性文件下载功能的函数代码(任意文件格式)
2010/05/26 PHP
使用PHP把HTML生成PDF文件的几个开源项目介绍
2014/11/17 PHP
判断、添加和删除WordPress置顶文章的相关PHP函数小结
2015/12/10 PHP
使用jscript实现二进制读写脚本代码
2008/06/09 Javascript
有关DOM元素与事件的3个谜题
2010/11/11 Javascript
jquery focus(fn),blur(fn)方法实例代码
2011/12/16 Javascript
jtable列中自定义button示例代码
2013/11/21 Javascript
利用JavaScript实现新闻滚动效果(实例代码)
2013/11/27 Javascript
Javascript基础教程之数组 array
2015/01/18 Javascript
JavaScript实现带标题的图片轮播特效
2015/05/20 Javascript
js实现微信分享代码
2020/10/11 Javascript
使用递归遍历对象获得value值的实现方法
2016/06/14 Javascript
浅析Node.js实现HTTP文件下载
2016/08/05 Javascript
javascript入门之string对象【新手必看】
2016/11/22 Javascript
基于slideout.js实现移动端侧边栏滑动特效
2016/11/28 Javascript
详解js中Number()、parseInt()和parseFloat()的区别
2016/12/20 Javascript
easyUI combobox实现联动效果
2017/01/17 Javascript
AngularJS报错$apply already in progress的解决方法分析
2017/01/30 Javascript
基于JavaScript实现类名的添加与移除
2017/04/23 Javascript
Angularjs cookie 操作实例详解
2017/09/27 Javascript
js 取消页面可以选中文字的功能方法
2018/01/02 Javascript
详解一个小实例理解js原型和继承
2019/04/24 Javascript
[01:02]DOTA2辉夜杯决赛日 CDEC.Y对阵VG赛前花絮
2015/12/27 DOTA
python根据距离和时长计算配速示例
2014/02/16 Python
python结合opencv实现人脸检测与跟踪
2015/06/08 Python
Python3 无重复字符的最长子串的实现
2019/10/08 Python
python字典排序的方法
2019/10/12 Python
Python函数必须先定义,后调用说明(函数调用函数例外)
2020/06/02 Python
详解python 支持向量机(SVM)算法
2020/09/18 Python
校长先进事迹材料
2014/02/01 职场文书
竞争上岗实施方案
2014/03/21 职场文书
面试自我介绍演讲稿
2014/04/29 职场文书
小学优秀班干部事迹材料
2014/05/25 职场文书
微软PC Health Check电脑健康状况检查应用下载(Win11配置检测工具)
2021/06/26 数码科技
python树莓派通过队列实现进程交互的程序分析
2021/07/04 Python
springboot用户数据修改的详细实现
2022/04/06 Java/Android