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

2024-01-16 10:08
文章标签 特性 多个 20 重温 事例 es10

本文主要是介绍20多个小事例带你重温 ES10 新特性,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

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

译文 | https://github.com/qq449245884/xiaozhi/issues/120

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

ES10 新特性主要如下:

  • 数组方法:flatflatMap

  • 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]

综合示例:

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 }

事例二:

3、String.protype.matchAll

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

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

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

正则表达式捕获组

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

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

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

字符串标本匹配:

这里创建了 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'blackravenlime*parrot at 11 with 'black*raven lime*parrot white*seagull'limeparrotwhite*seagull at 23 with 'black*raven lime*parrot white*seagull'whiteseagull

但奇怪的是:

如果你从这个正则表达式中删除 /g,你将永远在第一个结果上创建一个无限循环。这在过去是一个巨大的痛苦。想象一下,从某个数据库接收正则表达式时,你不确定它的末尾是否有 /g,你得先检查一下。

使用 .matchAll() 的好理由

  1. 在与捕获组一起使用时,它可以更加优雅,捕获组只是使用 () 提取模式的正则表达式的一部分。

  2. 它返回一个迭代器而不是一个数组,迭代器本身是有用的。

  3. 迭代器可以使用扩展运算符 (…) 转换为数组。

  4. 它避免了带有 /g 标志的正则表达式,当从数据库或外部源检索未知正则表达式并与陈旧的RegEx 对象一起使用时,它非常有用。

  5. 使用 RegEx 对象创建的正则表达式不能使用点 (.) 操作符链接。

  6. 高级: RegEx 对象更改跟踪最后匹配位置的内部 .lastindex 属性,这在复杂的情况下会造成严重破坏。

.matchAll() 是如何工作的?

咱们尝试匹配单词 hello 中字母 e 和 l 的所有实例, 因为返回了迭代器,所以可以使用 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'blackravenlime*parrot at 11 with 'black*raven lime*parrot white*seagull'limeparrotwhite*seagull at 23 with 'black*raven lime*parrot white*seagull'whiteseagull

也许在美学上它与原始正则表达式非常相似,执行while循环实现。但是如前所述,由于上面提到的许多原因,这是更好的方法,移除 /g 不会导致无限循环。

综合事例:

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

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

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

事例一:
let greeting = " Space around ";
greeting.trimEnd(); // " Space around";
greeting.trimStart(); // "Space around ";

事例二:

5、Symbol.Description

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

事例一:

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

事例二:

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

事例二:

7、JSON ⊂ ECMAScript

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

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

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

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

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

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

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

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

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

事例二:

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"

11、BigInt -任意精度整数

BigInt 是第七种 原始类型。

BigInt 是一个任意精度的整数。这意味着变量现在可以 表示²⁵³ 数字,而不仅仅是9007199254740992

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

在过去,不支持大于 9007199254740992 的整数值。如果超过,该值将锁定为 MAX_SAFE_INTEGER + 1:

const limit = Number.MAX_SAFE_INTEGER;⇨ 9007199254740991limit + 1;⇨ 9007199254740992limit + 2;⇨ 9007199254740992 <--- MAX_SAFE_INTEGER + 1 exceededconst larger = 9007199254740991n;⇨ 9007199254740991nconst integer = BigInt(9007199254740991); // initialize with number⇨ 9007199254740991nconst same = BigInt("9007199254740991"); // initialize with "string"⇨ 9007199254740991n

12、动态导入

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

事例一:

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

事例二:

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

总结

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

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

这篇关于20多个小事例带你重温 ES10 新特性的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/612214

相关文章

系统架构师考试学习笔记第三篇——架构设计高级知识(20)通信系统架构设计理论与实践

本章知识考点:         第20课时主要学习通信系统架构设计的理论和工作中的实践。根据新版考试大纲,本课时知识点会涉及案例分析题(25分),而在历年考试中,案例题对该部分内容的考查并不多,虽在综合知识选择题目中经常考查,但分值也不高。本课时内容侧重于对知识点的记忆和理解,按照以往的出题规律,通信系统架构设计基础知识点多来源于教材内的基础网络设备、网络架构和教材外最新时事热点技术。本课时知识

【C++学习笔记 20】C++中的智能指针

智能指针的功能 在上一篇笔记提到了在栈和堆上创建变量的区别,使用new关键字创建变量时,需要搭配delete关键字销毁变量。而智能指针的作用就是调用new分配内存时,不必自己去调用delete,甚至不用调用new。 智能指针实际上就是对原始指针的包装。 unique_ptr 最简单的智能指针,是一种作用域指针,意思是当指针超出该作用域时,会自动调用delete。它名为unique的原因是这个

ActiveMQ—消息特性(延迟和定时消息投递)

ActiveMQ消息特性:延迟和定时消息投递(Delay and Schedule Message Delivery) 转自:http://blog.csdn.net/kimmking/article/details/8443872 有时候我们不希望消息马上被broker投递出去,而是想要消息60秒以后发给消费者,或者我们想让消息没隔一定时间投递一次,一共投递指定的次数。。。 类似

PostgreSQL核心功能特性与使用领域及场景分析

PostgreSQL有什么优点? 开源和免费 PostgreSQL是一个开源的数据库管理系统,可以免费使用和修改。这降低了企业的成本,并为开发者提供了一个活跃的社区和丰富的资源。 高度兼容 PostgreSQL支持多种操作系统(如Linux、Windows、macOS等)和编程语言(如C、C++、Java、Python、Ruby等),并提供了多种接口(如JDBC、ODBC、ADO.NET等

【JavaScript】LeetCode:16-20

文章目录 16 无重复字符的最长字串17 找到字符串中所有字母异位词18 和为K的子数组19 滑动窗口最大值20 最小覆盖字串 16 无重复字符的最长字串 滑动窗口 + 哈希表这里用哈希集合Set()实现。左指针i,右指针j,从头遍历数组,若j指针指向的元素不在set中,则加入该元素,否则更新结果res,删除集合中i指针指向的元素,进入下一轮循环。 /*** @param

详解Tomcat 7的七大新特性和新增功能(1)

http://developer.51cto.com/art/201009/228537.htm http://tomcat.apache.org/tomcat-7.0-doc/index.html  Apache发布首个Tomcat 7版本已经发布了有一段时间了,Tomcat 7引入了许多新功能,并对现有功能进行了增强。很多文章列出了Tomcat 7的新功能,但大多数并没有详细解释它们

如何掌握面向对象编程的四大特性、Lambda 表达式及 I/O 流:全面指南

这里写目录标题 OOP语言的四大特性lambda输入/输出流(I/O流) OOP语言的四大特性 面向对象编程(OOP)是一种编程范式,它通过使用“对象”来组织代码。OOP 的四大特性是封装、继承、多态和抽象。这些特性帮助程序员更好地管理复杂的代码,使程序更易于理解和维护。 类-》实体的抽象类型 实体(属性,行为) -》 ADT(abstract data type) 属性-》成

struts2中的json返回指定的多个参数

要返回指定的多个参数,就必须在struts.xml中的配置如下: <action name="goodsType_*" class="goodsTypeAction" method="{1}"> <!-- 查询商品类别信息==分页 --> <result type="json" name="goodsType_findPgae"> <!--在这一行进行指定,其中lis是一个List集合,但

一款支持同一个屏幕界面同时播放多个视频的视频播放软件

GridPlayer 是一款基于 VLC 的免费开源跨平台多视频同步播放工具,支持在一块屏幕上同时播放多个视频。其主要功能包括: 多视频播放:用户可以在一个窗口中同时播放任意数量的视频,数量仅受硬件性能限制。支持多种格式和流媒体:GridPlayer 支持所有由 VLC 支持的视频格式以及流媒体 URL(如 m3u8 链接)。自定义网格布局:用户可以配置播放器的网格布局,以适应不同的观看需求。硬

《C++标准库》读书笔记/第一天(C++新特性(1))

C++11新特性(1) 以auto完成类型自动推导 auto i=42; //以auto声明的变量,其类型会根据其初值被自动推倒出来,因此一定需要一个初始化操作; static auto a=0.19;//可以用额外限定符修饰 vector<string> v;  auto pos=v.begin();//如果类型很长或类型表达式复杂 auto很有用; auto l=[] (int