ES13 中11个令人惊叹的 JavaScript 新特性
前言
与许多其他编程语言一样,JavaScript 也在不断发展。每年,该语言都会通过新功能变得更加强大,使开发人员能够编写更具表现力和简洁的代码。 小编今天就为大家介绍ES13中添加的最新功能,并查看其用法示例以更好地理解它们。
1.类
在ES13之前,类字段只能在构造函数中声明。与许多其他语言不同,无法在类的最外层作用域中声明或定义它们。
class Car {
constructor() {
this.color = 'blue';
this.age = 2;
}
}
const car = new Car();
console.log(car.color); // blue
console.log(car.age); //
而ES13 消除了这个限制。现在我们可以编写这样的代码:
class Car {
color = 'blue';
age = 2;
}const car = new Car();
console.log(car.color); // blue
console.log(car.age); // 2
2.私有方法和字段
ES13以前,不可能在类中声明私有成员。成员传统上带有下划线 ( _) 前缀,以表明它是私有的,但仍然可以从类外部访问和修改它。
class Person {
_firstName = 'Joseph';
_lastName = 'Stevens'; get name() {
return `${this._firstName} ${this._lastName}`;
}
}const person = new Person();
console.log(person.name); // Joseph Stevens
// 仍可以从类外部访问 // 原本打算设为私有的成员
console.log(person._firstName); // Joseph
console.log(person._lastName); // Stevens
// 也可以修改
person._firstName = 'Robert';
person._lastName = 'Becker';console.log(person.name); // Robert Becker
使用 ES13,我们现在可以通过在类前面添加 ( #) 来向类添加私有字段和成员。尝试从外部访问这些类将会引发错误:
class Person {
#firstName = 'Joseph';
#lastName = 'Stevens'; get name() {
return `${this.#firstName} ${this.#lastName}`;
}
}const person = new Person();
console.log(person.name);
// 语法错误:私有字段 '#firstName' 必须在一个外层类中声明
console.log(person.#firstName);
console.log(person.#lastName);
3.await顶层操作
在 JavaScript 中,await运算符用于暂停执行,直到 一个Promise被解决(执行或拒绝)。 以前只能在async中使用此运算符。不可以在全局作用域中直接使用await。
function setTimeoutAsync(timeout) {
return new Promise((resolve) => {
setTimeout(() => {
resolve();
}, timeout);
});
}
//语法错误:await 仅在异步函数中有效
await setTimeoutAsync(3000);
有了 ES13,现在我们可以:
function setTimeoutAsync(timeout) {
return new Promise((resolve) => {
setTimeout(() => {
resolve();
}, timeout);
});
}
// 等待超时 - 没有错误抛出
await setTimeoutAsync(3000);
4.静态类字段和静态私有方法
现在可以在 ES13 中为类声明静态字段和静态私有方法。静态方法可以使用关键字this访问类中的其他私有/公共静态成员,实例方法可以使用this.constructor访问他们。
class Person {
static #count = 0; static getCount() {
return this.#count;
} constructor() {
this.constructor.#incrementCount();
} static #incrementCount() {
this.#count++;
}
}const person1 = new Person();
const person2 = new Person();console.log(Person.getCount()); // 2
5.类静态块
ES13 引入了一项特性,允许开发者定义仅在创建类时执行一次的静态块。这一特性与其他面向对象编程语言(如 C# 和 Java)中的静态构造函数相似。
在一个类的主体中,你可以定义任意数量的静态 {} 初始化块。它们会按照声明的顺序与任何交错的静态字段初始值设定项一起执行。此外,你还可以通过块中的 super 关键字访问超类的静态属性。这为开发者提供了更多的灵活性和控制能力。
class Vehicle {
static defaultColor = 'blue';
}class Car extends Vehicle {
static colors = []; static {
this.colors.push(super.defaultColor, 'red');
} static {
this.colors.push('green');
}
}console.log(Car.colors); // [ 'blue', 'red', 'green' ]
6.检查对象中的私有字段
开发者如今可以利用这一新功能,使用运算符in来方便地检查对象是否包含某个特定的私有字段。
class Car {
#color; hasColor() {
return #color in this;
}
}const car = new Car();
console.log(car.hasColor()); // true;
通过运算符in,可以准确区分不同类中具有相同名称的私有字段。
class Car {
#color; hasColor() {
return #color in this;
}
}class House {
#color; hasColor() {
return #color in this;
}
}const car = new Car();
const house = new House();console.log(car.hasColor()); // true;
console.log(car.hasColor.call(house)); // false
console.log(house.hasColor()); // true
console.log(house.hasColor.call(car)); // false
7.at() 索引方法
在 JavaScript 中,我们通常使用方括号[]来访问数组的第 t 个元素。这个过程非常简单,但实际上我们只是访问了索引为 t-1 的数组属性而已。
const arr = ['a', 'b', 'c', 'd'];
console.log(arr[1]); // b
然而,当我们希望通过方括号来访问数组末尾的第 N 个元素时,我们需要使用索引 arr.length - N。
const arr = ['a', 'b', 'c', 'd'];
// 从末尾开始第一个元素
console.log(arr[arr.length - 1]); // d
// 倒数第二个元素 console.log
console.log(arr[arr.length - 2]); // c
借助全新的at()方法,可以以更加精简和富有表现力的方式来实现这一目标。要访问数组末尾的第N个元素,只需将负值-N作为参数传递给at()方法即可。
const arr = ['a', 'b', 'c', 'd'];
// 从末尾开始第一个元素
console.log(arr.at(-1)); // d
// 倒数第二个元素 console.log
console.log(arr.at(-2)); // c
除了数组之外,字符串和TypedArray对象现在也有at()方法。
const str = 'Coding Beauty';
console.log(str.at(-1)); // y
console.log(str.at(-2)); // tconst typedArray = new Uint8Array([16, 32, 48, 64]);
console.log(typedArray.at(-1)); // 64
console.log(typedArray.at(-2)); // 48
8.正则表达式匹配索引
在ES13之前,我们只能获取字符串中正则表达式匹配的起始索引,
const str = 'sun and moon';const regex = /and/;const matchObj = regex.exec(str);// [ 'and', index: 4, input: 'sun and moon', groups: undefined ]
console.log(matchObj);
使用ES13之后,可以通过指定一个/d正则表达式标志来获取匹配开始和结束的两个索引。这一特性赋予了更多的灵活性和控制能力。
const str = 'sun and moon';
const regex = /and/d;
const matchObj = regex.exec(str);
/**
[
'and',
index: 4,
input: 'sun and moon',
groups: undefined,
indices: [ [ 4, 7 ], groups: undefined ]
]
*/
console.log(matchObj);
设置标志后d,返回的对象将具有indices包含起始索引和结束索引的属性。
9.Object.hasOwn()方法
在 JavaScript 中,我们可以使用Object.prototype.hasOwnProperty()方法来检查对象是否具有给定的属性。
class Car {
color = 'green';
age = 2;
}const car = new Car();console.log(car.hasOwnProperty('age')); // true
console.log(car.hasOwnProperty('name')); // false
然而,这种方法存在一些问题。首先,Object.prototype.hasOwnProperty()方法并未受到保护,这意味着我们可以通过自定义的hasOwnProperty()方法来覆盖它,而这个自定义方法可能会具有与Object.prototype.hasOwnProperty()不同的行为。需要额外注意的是这一点。
class Car {
color = 'green';
age = 2; // This method does not tell us whether an object of
// this class has a given property.
hasOwnProperty() {
return false;
}
}const car = new Car();console.log(car.hasOwnProperty('age')); // false
console.log(car.hasOwnProperty('name')); // false
另外一个问题是,如果我们使用了 null 原型(通过 Object.create(null) 创建的对象),那么试图调用该方法将会产生错误。
const obj = Object.create(null);
obj.color = 'green';
obj.age = 2;
// TypeError: obj.hasOwnProperty 不是函数
console.log(obj.hasOwnProperty('color'));
为了克服这些问题,我们可以利用属性调用方法Object.prototype.hasOwnProperty.call()来解决。具体示例如下所示:
const obj = Object.create(null);
obj.color = 'green';
obj.age = 2;
obj.hasOwnProperty = () => false;console.log(Object.prototype.hasOwnProperty.call(obj, 'color')); // true
console.log(Object.prototype.hasOwnProperty.call(obj, 'name')); // false
这种方式并不十分便利。为了避免重复,我们可以编写一个可重用的函数,这样可以使我们的代码更加简洁和高效:
function objHasOwnProp(obj, propertyKey) {
return Object.prototype.hasOwnProperty.call(obj, propertyKey);
}const obj = Object.create(null);
obj.color = 'green';
obj.age = 2;
obj.hasOwnProperty = () => false;console.log(objHasOwnProp(obj, 'color')); // true
console.log(objHasOwnProp(obj, 'name')); // false
现在不需要在那样做了,我们还可以使用全新的内置方法Object.hasOwn()来处理这个问题。它与我们之前编写的可重用函数类似,接受对象和属性作为参数,并且返回一个布尔值,如果指定的属性是对象的直接属性,则返回true;否则返回false。
const obj = Object.create(null);
obj.color = 'green';
obj.age = 2;
obj.hasOwnProperty = () => false;console.log(Object.hasOwn(obj, 'color')); // true
console.log(Object.hasOwn(obj, 'name')); // false
10.错误原因属性
现在,错误对象已经增加了一个cause属性,该属性用于指定导致错误抛出的原始错误。通过这种方式,我们可以为错误添加额外的上下文信息,从而更好地诊断意外的行为。要指定错误的原因,我们可以在作为构造函数的第二个参数传递给Error()的对象中设置属性来实现。这种方法能够提供更丰富的错误追踪和调试信息。
function userAction() {
try {
apiCallThatCanThrow();
} catch (err) {
throw new Error('New error message', { cause: err });
}
}try {
userAction();
} catch (err) {
console.log(err);
console.log(`Cause by: ${err.cause}`);
}
11.从数组最后查找
在 JavaScript 中,我们已经可以使用Array的find()方法来查找数组中满足指定测试条件的元素。类似地,我们也可以使用findIndex()方法来获取满足条件的元素的索引值。尽管find()和findIndex()都是从数组的第一个元素开始搜索,但在某些情况下,从最后一个元素开始搜索可能会更有效。
有些情况下,我们知道从数组的末尾进行查找可能会获得更好的性能表现。例如,在这里我们尝试查找数组中prop属性等于"value"的项目。这时候,可以通过使用reverse()方法将数组反转,然后使用find()和findIndex()方法来从末尾开始搜索。下面是具体的实现示例:
const letters = [
{ value: 'v' },
{ value: 'w' },
{ value: 'x' },
{ value: 'y' },
{ value: 'z' },
];const found = letters.find((item) => item.value === 'y');
const foundIndex = letters.findIndex((item) => item.value === 'y');console.log(found); // { value: 'y' }
console.log(foundIndex); // 3
上面的代码可以获取正确结果,但由于目标对象更接近数组的尾部,如果我们使用findLast()和findLastIndex()方法来从数组的末尾进行搜索,很可能能够显著提升程序的执行效率。通过这种方式,我们可以更快地找到所需的元素或索引,从而优化代码性能。
const letters = [
{ value: 'v' },
{ value: 'w' },
{ value: 'x' },
{ value: 'y' },
{ value: 'z' },
];const found = letters.findLast((item) => item.value === 'y');
const foundIndex = letters.findLastIndex((item) => item.value === 'y');console.log(found); // { value: 'y' }
console.log(foundIndex); // 3
在一些特定的使用场景中,我们可能需要从数组的末尾开始搜索来获取准确的元素。举个例子,假设我们要查找数字列表中的最后一个偶数,使用find()或findIndex()方法可能会导致错误的结果:
const nums = [7, 14, 3, 8, 10, 9];
// 给出 14,而不是 10
const lastEven = nums.find((value) => value % 2 === 0);
// 给出 1,而不是 4
const lastEvenIndex = nums.findIndex((value) => value % 2 === 0);console.log(lastEven); // 14
console.log(lastEvenIndex); // 1
如果我们在调用reverse()方法之前使用数组的slice()方法创建新的数组副本,就可以避免不必要地改变原始数组的顺序。然而,在处理大型数组时,这种方法可能会导致性能问题,因为需要复制整个数组。
此外,findIndex()方法在反转数组时仍然无法达到预期效果,因为元素的反转会导致它们在原始数组中的索引改变。为了获取元素的原始索引,我们需要进行额外的计算,这意味着需要编写更多的代码来处理这种情况。
const nums = [7, 14, 3, 8, 10, 9];
// 在调用reverse()之前使用展开语法复制整个数组
// calling reverse()
const reversed = [...nums].reverse();
// 正确给出 10
const lastEven = reversed.find((value) => value % 2 === 0);
// 给出 1,而不是 4
const reversedIndex = reversed.findIndex((value) => value % 2 === 0);
// 需要重新计算得到原始索引
const lastEvenIndex = reversed.length - 1 - reversedIndex;console.log(lastEven); // 10
console.log(reversedIndex); // 1
console.log(lastEvenIndex); // 4
使用findLast()和findLastIndex()方法在需要查找数组中最后一个符合条件的元素或索引时非常实用。它们能够准确地定位目标对象,并且从数组末尾开始搜索,提供了高效的解决方案。
const nums = [7, 14, 3, 8, 10, 9];const lastEven = nums.findLast((num) => num % 2 === 0);
const lastEvenIndex = nums.findLastIndex((num) => num % 2 === 0);console.log(lastEven); // 10
console.log(lastEvenIndex); // 4
结论
ES13 为 JavaScript 带来了一系列令人振奋的新功能,我们已经有幸见识了它们的魅力。通过运用这些功能,开发人员的工作效率将得到极大提升,同时也能以更加简洁、明晰的方式书写出更加纯净、精炼的代码。这些新特性为我们带来了更大的灵活性和便利性,使得我们的开发过程更加高效、愉悦。
原文链接:https://medium.com/coding-beauty/es13-javascript-features-eed7ed2f1497
扩展链接:
React + Springboot + Quartz,从0实现Excel报表自动化
ES13 中11个令人惊叹的 JavaScript 新特性的更多相关文章
- 返璞归真 asp.net mvc (11) - asp.net mvc 4.0 新特性之自宿主 Web API, 在 WebForm 中提供 Web API, 通过 Web API 上传文件, .net 4.5 带来的更方便的异步操作
原文:返璞归真 asp.net mvc (11) - asp.net mvc 4.0 新特性之自宿主 Web API, 在 WebForm 中提供 Web API, 通过 Web API 上传文件, ...
- 【广州.NET社区推荐】【译】Visual Studio 2019 中 WPF & UWP 的 XAML 开发工具新特性
原文 | Dmitry 翻译 | 郑子铭 自Visual Studio 2019推出以来,我们为使用WPF或UWP桌面应用程序的XAML开发人员发布了许多新功能.在本周的 Visual Studio ...
- ES6:JavaScript 新特性
我相信,在ECMAScript.next到来的时候,我们现在每天都在写的JavaScript代码将会发生巨大的变化.接下来的一年将会是令JavaScript开发者们兴奋的一年,越来越多的特性提案将被最 ...
- javascript新特性
让我们看看javascript中的一些新特性.本文将介绍它们的语法和相关链接,以帮助读者及时了解它们的进展.我们将通过编写一个小测试项目来演示如何快速使用这些新功能! 关于提案 提案分为五个阶段.有关 ...
- 7 个令人兴奋的 JavaScript 新特性
前言 一个ECMAScript标准的制作过程,包含了Stage 0到Stage 4五个阶段,每个阶段提交至下一阶段都需要TC39审批通过.本文介绍这些新特性处于Stage 3或者Stage 4阶段,这 ...
- oracle11g中SQL优化(SQL TUNING)新特性之SQL Plan Management(SPM)
1. 简介 Oracle Database11gR1引进了SQL PlanManagement(简称SPM),一套允许DBA捕获和保持任意SQL语句执行计划最优的新工具,这样,限制了刷新优化器统计 ...
- [译]C#8.0中一个使接口更加灵活的新特性-默认接口实现
9月份的时候,微软宣布正式发布C#8.0,作为.NET Core 3.0发行版的一部分.C#8.0的新特性之一就是默认接口实现.在本文中,我们将一起来聊聊默认接口实现. 众所周知,对现有应用程序的接口 ...
- 七种武器:JavaScript 新特性闪亮登场
JavaScript(或ECMA Script) 是一门不断发展的语言,有许多关于如何前进的建议和想法.TC39(技术委员会39)是负责定义JS标准和特性的委员会,今年他们非常活跃.以下是目前处于&q ...
- Oracle12c中SQL优化(SQL TUNING)新特性之SQL计划指令
SQL计划指令是Oracle12c中自适应查询优化的功能之一.SQL计划指令就像“额外的提醒” ,用以提醒优化器你先前选择了的计划并不是最优的,典型的是因为错误的势评估.错误的势评估往往是由统计信息缺 ...
- oracle11g中SQL优化(SQL TUNING)新特性之Adaptive Cursor Sharing (ACS)
1. ACS简介 Oracle Database 11g提供了Adaptive Cursor Sharing (ACS)功能,以克服以往不该共享的游标被共享的可能性.ACS使用两个新指标:sens ...
随机推荐
- react中useRef的应用
何为useRef useRef是随着react函数式组件发展而来的,是react众多官方hook中的一个,调用useRef可以返回一个伴随这组件整个声明周期不发生改变的对象,这个对象常见的用途有两个: ...
- IntelliJ IDEA 最新激活码:2023、2022及以下版本通用(亲测有效)
分享一下 IntelliJ IDEA 2023.1 最新激活注册码,破解教程如下,可免费永久激活,亲测有效,下面是详细文档哦~ 申明:本教程 IntelliJ IDEA 破解补丁.激活码均收集于网络, ...
- 华为防火墙NAT技术
---我是陈小瓜,一个普通的路人,和大家一起交流学习,完善自己. 源NAT NAT-no-pat 安全策略写法: 源NAT,写安全策略,写转换前的私网IP,因为先匹配安全策略.再匹配NAT策略 NAT ...
- SpringBoot进阶教程(七十六)多维度排序查询
在项目中经常能遇到,需要对某些数据集合进行多维度排序的需求.对于集合多条件排序解决方案也有很多,今天我们就介绍一种,思路大致是设置一个分值的集合,这个分值是按照需求来设定大小的,再根据分值的大小对集合 ...
- CF1442D Sum
题意 有 \(n\) 个不降的非负整数数组,每个数组可以不取或取一个前缀,总共要取 \(k\) 个元素,问取到的和最大多少. 题解 结论题,但是想到结论还不会. 首先,我们只会有一个数组没选完,其它要 ...
- AI室内设计:提升效率、消除沟通障碍,满足客户需求
前言 免费AI绘图工具:https://www.topgpt.one 随着人工智能(AI)技术的不断发展,室内设计行业也开始受益于这一技术的应用.其中,AI绘画工具在室内设计中的应用正日益受到关注.这 ...
- 自己动手实现rpc框架(二) 实现集群间rpc通信
自己动手实现rpc框架(二) 实现集群间rpc通信 1. 集群间rpc通信 上一篇博客中MyRpc框架实现了基本的点对点rpc通信功能.而在这篇博客中我们需要实现MyRpc的集群间rpc通信功能. 自 ...
- Java扩展Nginx之三:基础配置项
欢迎访问我的GitHub 这里分类和汇总了欣宸的全部原创(含配套源码):https://github.com/zq2599/blog_demos 本篇概览 经历了前面两篇的入门和编译源码之后,从本篇起 ...
- Windows系统使用Nginx部署Vue
Nginx是什么? Nginx (engine x) 是一个高性能的HTTP和反向代理web服务器 ,同时也提供了IMAP/POP3/SMTP服务.Nginx是由伊戈尔·赛索耶夫为俄罗斯访问量第二的R ...
- 即构发布 LCEP 低代码互动平台产品 RoomKit,实现互动房间0代码搭建
2月5日,全球云通讯服务商ZEGO即构科技发布低代码互动平台 LCEP(Low-code Engagement Platform)产品 RoomKit,支持1V1在线课堂.小班课.大班课.视频会议.视 ...