感兴趣的能够加微信群

如果过期能够底下留言,或者关注我的微信公众号 《人生代码》《人生代码》《人生代码》,回复进群,加我微信,拉你进群,重要的事件说三遍。

JavaScript行将推出令人兴奋的新性能!

即便新ECMAScript 2020(ES2020)语言标准的最终批准曾经在六月,您也能够立刻开始尝试一下!

解决模块

一些重要的翻新波及模块。其中,开发人员长期以来始终要求的性能是动静导入。然而,让咱们按程序进行具体介绍。

动静导入

以后的模块导入机制基于动态申明,如下所示:

import * as MyModule from "./my-module.js";

该语句有两个束缚:
在以后模块的加载工夫评估导入模块的所有代码
该模块的说明符("./my-module.js"在下面的示例中)是一个字符串常量,您不能在运行时更改它

这些束缚阻止有条件或按需加载模块。同样,在加载时评估每个相干模块也会影响应用程序的性能。
新import()语句通过容许您动静导入模块来解决了这些问题。该语句承受模块说明符作为参数并返回promise。同样,模块说明符能够是任何返回字符串的表达式。这是个好消息,因为咱们当初能够在运行时加载JavaScript模块,如以下示例所示:

const baseModulePath = "./modules";const btnBooks = document.getElementById("btnBooks");let bookList = [];btnBooks.addEventListener("click", async e => {  const bookModule = await import(`${baseModulePath}/books.js`);  bookList = bookModule.loadList();});

该代码显示books.js了用户单击btnBooks按钮时如何正确加载模块。加载模块后,click事件处理程序将应用loadList()模块导出的性能。请留神如何通过字符串插值指定要导入的模块。
导入元数据
该import.meta对象提供以后模块的元数据。JavaScript引擎创立了它,其以后可用属性为url。此属性的值是从中加载模块的URL,包含任何查问参数或哈希。
例如,您能够应用该import.meta.url属性来构建data.json存储在以后模块雷同文件夹中的文件的URL 。以下代码取得此后果:

const dataUrl = new URL("data.json", import.meta.url);

在这种状况下,会import.meta.url为URL该类提供data.json文件的根本URL 。

新的导出语法

importECMAScript 2015标准引入的申明为您提供了多种形式的模块导入。以下是一些示例:

import {value} from "./my-module.js";import * from "./my-module.js";

在某些状况下,您可能须要导出从另一个模块导入的对象。不便的export语法可能会对您有所帮忙,如下所示:

export {value} from "./my-module.js";export * from "./my-module.js";

从开发人员的教训来看,导入和导出语句之间的这种对称性很不便。然而,在这些新标准之前不反对特定状况:

import * as MyModule from "./my-module.js";

要导出MyModule名称空间,应应用两个语句:

import * as MyModule from "./my-module.js";export {MyModule};

当初,您能够通过一条语句取得雷同的后果,如下所示:

export * as MyModule from "./my-module.js";

这种增加简化了您的代码,并使import和export语句之间放弃对称。

数据类型和对象

新的ES2020标准引入了新的数据类型,标准化的全局对象以及一些简化开发人员生存的办法。让咱们来看看。

BigInt和任意精度整数

如您所知,JavaScript只有一种数据类型:数字Number。这种原始类型容许您示意64位浮点数。当然,它也示意整数,然而最大可示意值为2 53,对应于Number.MAX_SAFE_INTEGER常数。
在不波及整数示意的外部细节的状况下,有些状况下您可能须要更高的精度。思考以下状况:
与其余提供64位整数数据的零碎(例如GUID,帐号或对象ID)进行交互
须要超过64位的简单数学计算的后果

第一种状况的解决办法是将数据表示为字符串。当然,这种解决办法不适用于第二种状况。
新的BigInt数据类型旨在解决这些问题。您能够BigInt通过将字母简略地附加n到数字来示意文字,如以下示例所示:

const aBigInteger = 98765432123456789n;

您也能够像应用BigInt()构造函数一样应用Number()构造函数:

const aBigInteger = BigInt("98765432123456789");

typeof当初,运算符将"bigint"利用于BigInt值的字符串返回:

typeof aBigInteger      //output: "bigint"

请记住,Number并且BigInt是不同类型的,所以你不能将它们混合。例如,尝试将Number值增加到BigInt值会引发TypeError异样,如下图所示:

您必须应用构造函数将Number值显式转换为值。BigIntBigInt()

用于正则表达式的matchAll()办法

您能够通过多种形式获取给定正则表达式的所有匹配项。以下是这些办法之一,然而您能够应用其余办法:

const regExp = /page (\d+)/g;const text = 'text page 1 text text page 2';let matches;while ((matches = regExp.exec(text)) !== null) {  console.log(matches);}

此代码通过迭代匹配变量中的所有page x实例text。在每次迭代时,该exec()办法都会在输出字符串上运行,并且您将取得如下后果:

["page 1", "1", index: 5, input: "text page 1 text text page 2", groups: undefined]["page 2", "2", index: 22, input: "text page 1 text text page 2", groups: undefined]

该matchAll()办法String的对象,您能够失去雷同的后果,但在更紧凑的形式和更好的性能。上面的示例应用此新办法重写以前的代码:

const regExp = /page (\d+)/g;const text = 'text page 1 text text page 2';let matches = [...text.matchAll(regExp)];for (const match of matches) {  console.log(match);}

该matchAll()办法返回一个迭代器。后面的示例应用流传运算符将迭代器的后果收集到数组中。

全局对象

拜访全局对象须要不同的语法,具体取决于JavaScript环境。例如,在浏览器中,全局对象是window,然而您不能在Web Worker中应用它。在这种状况下,您须要应用self。另外,在Node.js中,全局对象是global。
在编写旨在在不同环境中运行的代码时,这会导致问题。您可能应用了this关键字,然而它undefined在以严格模式运行的模块和函数中。
该globalThis对象提供了一种跨不同JavaScript环境拜访全局对象的规范办法。因而,当初您能够以统一的形式编写代码,而不用查看以后的运行环境。然而请记住,要尽量减少应用全局项,因为这被认为是不好的编程习惯。

Promise.allSettled()办法

目前,JavaScript有两种办法来组合诺言:Promise.all()和Promise.race()。
两种办法都将一个promise数组作为参数。以下是应用示例Promise.all():

const promises = [fetch("/users"), fetch("/roles")];const allResults = await Promise.all(promises);

Promise.all()当所有的诺言都实现时,返回一个诺言。如果至多一个诺言被回绝,则返回的诺言被回绝。最终承诺的回绝起因与第一个回绝的承诺雷同。
当至多一个承诺被回绝时,这种行为无奈为您提供间接取得所有承诺后果的办法。例如,在下面的代码中,如果fetch("/users")失败并且相应的诺言被回绝,您将没有一个简略的办法来晓得的诺言fetch("/roles")是兑现还是被回绝。要取得此信息,您必须编写一些其余代码。
新的Promise.allSettled()组合器将期待所有诺言的兑现,无论其后果如何。因而,以下代码可让您晓得每个诺言的后果:

const promises = [fetch("/users"), fetch("/roles")];const allResults = await Promise.allSettled(promises);const errors = results  .filter(p => p.status === 'rejected')  .map(p => p.reason);

特地是,此代码使您晓得每个被回绝的承诺失败的起因。

新运营商

几个新的运算符将使在十分常见的操作中更容易编写和浏览代码。猜猜哪一个?

空合并运算符

您看过多少次并应用了以下表达式?

const size = settings.size || 42;

||当您尝试调配的默认值是null或时,通常应用运算符来调配默认值undefined。然而,这种办法可能会导致一些潜在的意外后果。
例如,size下面示例中的常量42也将在settings.sizeis的值时被赋值0。然而,当值的默认值也将被指定settings.size为""或false。
为了克服这些潜在的问题,当初您能够应用有效的合并运算符(??)。先前的代码如下:

const size = settings.size ?? 42;

这容许仅在值为is或时42将默认值调配给size常数。settings.sizenullundefined

可选链接

思考以下示例:

const txtName = document.getElementById("txtName");const name = txtName ? txtName.value : undefined;

您txtName将从以后HTML文档中取得带有其标识符的文本框。然而,如果文档中不存在HTML元素,则txtName常量将为null。因而,在拜访其value属性之前,必须确保txtName不是null或undefined。
可选的链接运算符(?.)使您能够领有更紧凑,更易读的代码,如下所示:

const txtName = document.getElementById("txtName");const name = txtName?.value;

与后面的示例一样,该name常量的值将为txtName.valueif txtNameis notnull或undefined;; undefined除此以外。
在如下所示的简单表达式中,此运算符的长处失去了更多的赞叹:

const customerCity = invoice?.customer?.address?.city;

您还能够将可选的链接运算符利用于动静属性,如以下示例所示:

const userName = user?.["name"];

此外,它也实用于函数或办法调用:

const fullName = user.getFullName?.();

在这种状况下,如果该getFullName()办法存在,则将执行该办法。否则,表达式返回undefined。

应用新性能

在整篇文章中,您对ES2020的新性能进行了概述,并且您可能想晓得何时能力应用它们。
依据caniuse.com的材料,所有最近的支流浏览器(但Internet Explorer)曾经反对ECMAScript 2020带来的新性能。然而,在撰写本文时,Safari并不反对新的BigInt数据类型和matchAll()办法。
在Node.js的最新版本,反对所有性能,以及包含动静导入的启用ECMAScript的模块。
最初,Babel和TypeScript等最受欢迎的编译器的最新版本也使您能够应用最新的ES2020性能。

旁:应用JavaScript进行Auth0身份验证
在Auth0,咱们大量应用了全栈JavaScript来帮忙客户治理用户身份,包含明码重置,创立,供给,阻止和删除用户。因而,毫无疑问,在JavaScript Web应用程序上应用咱们的身份治理平台几乎是小菜一碟。
Auth0提供了一个收费层,能够开始应用古代身份验证。签出,或在此处注册收费的Auth0帐户!
而后,转到Auth0信息中心的“应用程序”局部,而后单击“创立应用程序”。在显示的对话框上,设置应用程序的名称,而后抉择“单页Web应用程序”作为应用程序类型:

创立应用程序后,单击“设置”,并记下调配给您的应用程序的域和客户端ID。另外,将“容许的回调URL”和“容许的登记URL”字段设置为将解决Auth0的登录和登记响应的页面的URL。在以后示例中,页面的URL将蕴含您要编写的代码(例如http://localhost:8080)。
当初,在您的JavaScript我的项目中,如下装置auth0-spa-js库:

npm install @auth0/auth0-spa-js

而后,在您的JavaScript利用中实现以下内容:

import createAuth0Client from '@auth0/auth0-spa-js';let auth0Client;async function createClient() {  return await createAuth0Client({    domain: 'YOUR_DOMAIN',    client_id: 'YOUR_CLIENT_ID'  });}async function login() {  await auth0Client.loginWithRedirect();}function logout() {  auth0Client.logout();}async function handleRedirectCallback() {  const isAuthenticated = await auth0Client.isAuthenticated();  if (!isAuthenticated) {    const query = window.location.search;    if (query.includes("code=") && query.includes("state=")) {      await auth0Client.handleRedirectCallback();      window.history.replaceState({}, document.title, "/");    }  }  await updateUI();}async function updateUI() {  const isAuthenticated = await auth0Client.isAuthenticated();  const btnLogin = document.getElementById("btn-login");  const btnLogout = document.getElementById("btn-logout");  btnLogin.addEventListener("click", login);  btnLogout.addEventListener("click", logout);  btnLogin.style.display = (isAuthenticated ? "none" : "block");  btnLogout.style.display = (isAuthenticated ? "block" : "none");  if (isAuthenticated) {    const username = document.getElementById("username");    const user = await auth0Client.getUser();    username.innerText = user.name;  }}window.addEventListener("load", async () => {  auth0Client = await createClient();  await handleRedirectCallback()});

将YOUR_DOMAIN和YOUR_CLIENT_ID占位符替换为您在Auth0信息中心中找到的域和客户端ID的理论值。
而后,应用以下标记创立UI:

<p>Welcome <span id="username"></span></p>  <button type="submit" id="btn-login">Sign In</button>  <button type="submit" id="btn-logout" style="display:none;">Sign Out</button>

您的应用程序已筹备好通过Auth0进行身份验证!
请查看Auth0 SPA SDK文档,以理解无关应用JavaScript和Auth0进行身份验证和受权的更多信息。