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 相关文章推荐
js简单实现HTML标签Select联动带跳转
Oct 23 Javascript
Java File类的常用方法总结
Mar 18 Javascript
为何JS操作的href都是javascript:void(0);呢
Nov 12 Javascript
javascript匀速运动实现方法分析
Jan 08 Javascript
JS组件Bootstrap Table使用方法详解
Feb 02 Javascript
WEB前端开发框架Bootstrap3 VS Foundation5
May 16 Javascript
vuejs通过filterBy、orderBy实现搜索筛选、降序排序数据
Oct 26 Javascript
jquery easyui dataGrid动态改变排序字段名的方法
Mar 02 Javascript
老生常谈js中的MVC
Jul 25 Javascript
对类Vue的MVVM前端库的实现代码
Sep 07 Javascript
Vue+Element实现网页版个人简历系统(推荐)
Dec 31 Javascript
el-form 多层级表单的实现示例
Sep 10 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
使用pthreads实现真正的PHP多线程(需PHP5.3以上版本)
2014/05/05 PHP
Laravel中任务调度console使用方法小结
2017/05/07 PHP
JS小功能(操作Table--动态添加删除表格及数据)实现代码
2013/11/28 Javascript
弹出窗口并且此窗口带有半透明的遮罩层效果
2014/03/13 Javascript
JQuery中绑定事件(bind())和移除事件(unbind())
2015/02/27 Javascript
jQuery图片轮播滚动切换代码分享
2020/04/20 Javascript
javascript动态添加checkbox复选框的方法
2015/12/23 Javascript
JavaScript知识点总结(十六)之Javascript闭包(Closure)代码详解
2016/05/31 Javascript
详解Vue.js动态绑定class
2016/12/20 Javascript
Vue学习笔记进阶篇之单元素过度
2017/07/19 Javascript
Angular弹出模态框的两种方式
2017/10/19 Javascript
深入理解 Koa 框架中间件原理
2018/10/18 Javascript
vue地址栏直接输入路由无效问题的解决
2018/11/15 Javascript
浅谈ng-zorro使用心得
2018/12/03 Javascript
JS开发常用工具函数(小结)
2019/07/04 Javascript
Vue实现点击箭头上下移动效果
2020/06/11 Javascript
Openlayers测量距离与面积的实现方法
2020/09/25 Javascript
[49:12]完美世界DOTA2联赛PWL S2 Magma vs GXR 第二场 11.29
2020/12/02 DOTA
Python程序中使用SQLAlchemy时出现乱码的解决方案
2015/04/24 Python
numpy中实现ndarray数组返回符合特定条件的索引方法
2018/04/17 Python
Python使用Dijkstra算法实现求解图中最短路径距离问题详解
2018/05/16 Python
jupyter notebook 中输出pyecharts图实例
2020/04/23 Python
pycharm new project变成灰色的解决方法
2019/06/27 Python
python pandas生成时间列表
2019/06/29 Python
Expected conditions模块使用方法汇总代码解析
2020/08/13 Python
详解移动端h5页面根据屏幕适配的四种方案
2020/04/15 HTML / CSS
美国一家主营日韩美妆护肤品的在线商店:iMomoko
2016/09/11 全球购物
大学毕业感言一句话
2014/02/06 职场文书
晚归检讨书
2014/02/19 职场文书
理财计划书
2014/08/14 职场文书
2015年学校综合治理工作总结
2015/07/20 职场文书
Python机器学习之KNN近邻算法
2021/05/14 Python
使用Python的开发框架Brownie部署以太坊智能合约
2021/05/28 Python
20180830晚上第一届KSL半决赛 雨神vs解冻(二龙 三炮解说)
2022/04/01 星际争霸
Python 全局空间和局部空间
2022/04/06 Python
JavaScript原型链中函数和对象的理解
2022/06/16 Javascript