ES10 虽然没有像 ES6 那么多新特性,但 ES10 仍然有一些有用的特性。文本通过简单示例来介绍了 ES10 新出来的特性。通过这种方式,咱们就可以快速理解,而不需要看太多的官方解释。
ES10 新特性主要如下:
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'
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() 的好理由
.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' 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 不会导致无限循环。
综合事例:
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; ⇨ 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
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应用程序的开发可能不是必需的,但是一些特性可以规制咱们以前通过技巧或大量冗长实现的代码。
代码部署后可能存在的BUG没法实时知道,事后为了解决这些BUG,花了大量的时间进行log 调试,这边顺便给大家推荐一个好用的BUG监控工具 Fundebug。
原文:https://dev.to/carlillo/12-es10-features-in-12-simple-examples-2cbn
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持小牛知识库。
本文向大家介绍PHP5.3新特性小结,包括了PHP5.3新特性小结的使用技巧和注意事项,需要的朋友参考一下 本文总结分析了PHP5.3新特性。分享给大家供大家参考,具体如下: 1、命名空间 解决了类,函数和常量名冲突的问题 2、静态绑定 继承时父类可以直接调用子类重写父类的方法 3、匿名函数,也叫闭包函数(closures),允许 临时创建一个没有指定名称的函数。最经常用作回调函数 闭包函数也可以
本文向大家介绍浅谈目前可以使用ES10的5个新特性,包括了浅谈目前可以使用ES10的5个新特性的使用技巧和注意事项,需要的朋友参考一下 ECMAScript 2015,也称为ES6,是一个花了6年时间完成的主要版本。从那时起,负责ECMAScript标准开发的技术委员会39 (TC39)每年都会发布该标准的新版本。这个年度发布周期简化了这个过程,并使新特性快速可用,JavaScript社区对此表示
本文向大家介绍JDK 7 新特性小结实例代码解析,包括了JDK 7 新特性小结实例代码解析的使用技巧和注意事项,需要的朋友参考一下 1、switch支持String做参数 switch枚举支持 2、数字字面量的改进 2.1. Java7 前支持 十进制(1234)、八进制(01234)、十六进制(0x1234) Java 8支持二进制(0B11110001) 2.2. 可以使用下划线
本文向大家介绍你可能从未使用过的11+个JavaScript特性(小结),包括了你可能从未使用过的11+个JavaScript特性(小结)的使用技巧和注意事项,需要的朋友参考一下 重要 这篇文章中描述的大多数功能已被暂停使用(甚至不推荐使用)。 它们仍然在许多图书中很常见,因此值得学习。 一、逗号运算符 , 是用于分隔表达式并返回链中最后一个表达式的运算符。 这里有三个主要表达式 1 、 2 和
本文向大家介绍VC程序设计小技巧20例,包括了VC程序设计小技巧20例的使用技巧和注意事项,需要的朋友参考一下 本文汇总了VC程序设计中常用的20则技巧实例,供大家参考。详情如下: 1、打开CD-ROM 2、关闭CD_ROM 3、关闭计算机 4、重启计算机 5、枚举所有字体 其中m_ctlFontList是一个列表控件变量 6、一次只运行一个程序实例,如果已运行则退出 7、得到当前鼠标所在位置 8
本文向大家介绍一文带你入门JDK8新特性——Lambda表达式,包括了一文带你入门JDK8新特性——Lambda表达式的使用技巧和注意事项,需要的朋友参考一下 Lambda简介 Lambda 表达式是 JDK8 的一个新特性,可以取代大部分的匿名内部类,写出更优雅的 Java 代码,尤其在集合的遍历和其他集合操作中,可以极大地优化代码结构。 JDK 也提供了大量的内置函数式接口供我们使用,使得 L
本文向大家介绍ES6 Object属性新的写法实例小结,包括了ES6 Object属性新的写法实例小结的使用技巧和注意事项,需要的朋友参考一下 本文实例讲述了ES6 Object属性新的写法。分享给大家供大家参考,具体如下: 之前我们定义一个对象特别麻烦,现在ES6简化了这些麻烦,在对象属性的新定义方法中存在以下的优化 我们之前定义对象属性的方法 比较的麻烦 ES6中属性新的定义方法,极简主义 简
本文向大家介绍20个必会的JavaScript面试题(小结),包括了20个必会的JavaScript面试题(小结)的使用技巧和注意事项,需要的朋友参考一下 问题1:JavaScript 中 undefined 和 not defined 的区别 JavaScript 未声明变量直接使用会抛出异常:var name is not defined,如果没有处理异常,代码就停止运行了。 但是,使用typ