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 相关文章推荐
jQuery 技巧大全(新手入门篇)
May 12 Javascript
jQuery ui 1.7更新小结
Aug 15 Javascript
jquery.ajax的url中传递中文乱码问题的解决方法
Feb 07 Javascript
jQuery内容过滤选择器用法分析
Feb 10 Javascript
javascript比较两个日期相差天数的方法
Jul 24 Javascript
浅谈javascript中replace()方法
Nov 10 Javascript
jquery自定义右键菜单、全选、不连续选择
Mar 01 Javascript
Node.js返回JSONP详解
May 18 Javascript
JS及PHP代码编写八大排序算法
Jul 12 Javascript
JS添加或修改控件的样式(Class)实现方法
Oct 15 Javascript
jQuery解析返回的xml和json方法详解
Jan 05 Javascript
Vue OpenLayer测距功能的实现
Apr 20 Vue.js
解决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
DedeCMS dede_channeltype表字段注释
2010/04/07 PHP
php可扩展的验证类实例(可对邮件、手机号、URL等验证)
2015/07/09 PHP
深入浅析用PHP实现MVC
2016/03/02 PHP
微信公众号之主动给用户发送消息功能
2019/06/22 PHP
解决 firefox 不支持 document.all的方法
2007/03/12 Javascript
javascript 尚未实现错误解决办法
2008/11/27 Javascript
JS实现匀速运动的代码实例
2013/11/29 Javascript
Node调试工具JSHint的安装及配置教程
2014/05/27 Javascript
自编jQuery插件实现模拟alert和confirm
2014/09/01 Javascript
js制作简易年历完整实例
2015/01/28 Javascript
jQuery获取剪贴板内容的方法
2016/06/16 Javascript
jQuery实现图片滑动效果
2017/03/08 Javascript
jQuery实现鼠标滑过预览图片大图效果的方法
2017/04/26 jQuery
Vue2 使用 Echarts 创建图表实例代码
2017/05/18 Javascript
jQuery获取复选框选中的当前行的某个字段的值
2017/09/15 jQuery
JavaScript中this的学习笔记及用法整理
2020/02/17 Javascript
浅析Vue 中的 render 函数
2020/02/28 Javascript
Python3基础之输入和输出实例分析
2014/08/18 Python
python调用机器喇叭发出蜂鸣声(Beep)的方法
2015/03/23 Python
Pycharm学习教程(5) Python快捷键相关设置
2017/05/03 Python
基于Python List的赋值方法
2018/06/23 Python
python使用tcp实现局域网内文件传输
2020/03/20 Python
python中redis查看剩余过期时间及用正则通配符批量删除key的方法
2018/07/30 Python
Python列表list操作相关知识小结
2020/01/29 Python
使用python求斐波那契数列中第n个数的值示例代码
2020/07/26 Python
Oakley官网:运动太阳镜、雪镜和服装
2016/09/30 全球购物
Bose英国官方网站:美国知名音响品牌
2020/01/26 全球购物
关联、聚合(Aggregation)以及组合(Composition)的区别
2012/02/29 面试题
派出所副所长四风问题个人整改措施思想汇报
2014/10/13 职场文书
医院营销工作计划
2015/01/16 职场文书
乡镇科协工作总结2015
2015/05/19 职场文书
军训决心书范文
2015/09/22 职场文书
CSS3点击按钮圆形进度打钩效果的实现代码
2021/03/30 HTML / CSS
聊聊Python中关于a=[[]]*3的反思
2021/06/02 Python
2021年国产动漫公司排行前十名,玄机科技上榜,第二推出过铠甲勇士
2022/03/18 杂记
解决MySQL Varchar 类型尾部空格的问题
2022/04/06 MySQL